Ink! contracts for a collateralized TUSDT system with vault borrowing, interest accrual, and liquidation auctions.
- Rust stable toolchain
wasm32-unknown-unknowntargetcargo-contract- Node.js + Yarn (for the isolated contract tooling under
tools/) - A Contracts-enabled Substrate node (local or remote)
rustup target add wasm32-unknown-unknown
cargo install --locked cargo-contractBuild all crates:
cargo checkBuild contract artifacts (.contract, .wasm, metadata):
cargo contract build --manifest-path contracts/tusdt-erc20/Cargo.toml
cargo contract build --manifest-path contracts/tusdt-auction/Cargo.toml
cargo contract build --manifest-path contracts/tusdt-oracle/Cargo.toml
cargo contract build --manifest-path contracts/tusdt-vault/Cargo.tomlArtifacts are produced in target/ink/.
Shared deployment scripts and on-chain tests live in an isolated TypeScript subproject under tools/.
The current iteration exposes upload support for erc20, auction, oracle, and vault, plus a single vault deployment entrypoint that instantiates the whole runtime flow.
Setup:
cd tools
yarn install
cp .env.example .envDefault .env values target a local dev node:
WS_URL=ws://127.0.0.1:9944
Scripts and tests use the standard local dev accounts (//Alice, //Bob, //Charlie, //Dave, //Eve, //Ferdie) from the shared dev-account helper.
When needed, you can override the selected account via SURI environment variables such as CONTRACT_UPLOADER=//Alice, CONTRACT_DEPLOYER=//Alice.
Useful commands:
cd tools
yarn build:erc20-artifacts
yarn build:auction-artifacts
yarn build:oracle-artifacts
yarn build:vault-artifacts
yarn erc20:upload
yarn auction:upload
yarn oracle:upload
yarn vault:upload
yarn vault:deploy --token-code-hash <TOKEN_CODE_HASH> --auction-code-hash <AUCTION_CODE_HASH> --oracle-code-hash <ORACLE_CODE_HASH>
yarn test:oracletusdt-vault constructor requires the code hash of the token, auction, and oracle contracts, then instantiates all three internally.
- Upload ERC20 code (
tusdt-erc20) and capture code hash. - Upload Auction code (
tusdt-auction) and capture code hash. - Upload Oracle code (
tusdt-oracle) and capture code hash. - Instantiate Vault (
tusdt-vault::new) with:token_code_hashauction_code_hashoracle_code_hash
The deployed vault owner becomes the oracle owner during instantiation.
Example CLI (adjust URL/account):
cargo contract upload \
--manifest-path contracts/tusdt-erc20/Cargo.toml \
--suri //Alice --url ws://127.0.0.1:9944
cargo contract upload \
--manifest-path contracts/tusdt-auction/Cargo.toml \
--suri //Alice --url ws://127.0.0.1:9944
cargo contract upload \
--manifest-path contracts/tusdt-oracle/Cargo.toml \
--suri //Alice --url ws://127.0.0.1:9944
cargo contract instantiate \
--manifest-path contracts/tusdt-vault/Cargo.toml \
--constructor new \
--args <ERC20_CODE_HASH> <AUCTION_CODE_HASH> <ORACLE_CODE_HASH> \
--suri //Alice --url ws://127.0.0.1:9944Prefer the tools/ workflow above instead of using cargo contract for upload/deploy operations where a TS script already exists.
The current e2e test suite is intentionally oracle-only, and the only deployment script entrypoint is vault:deploy.
- User creates vault with native collateral:
create_vault(payable). - User adds collateral:
add_collateral(payable). - User borrows token:
borrow_token. - User repays token:
repay_token. - User releases collateral (only when debt is zero):
release_collateral.
- Accrual is day-based.
- Growth model is compound interest equivalent to:
borrowed * e^(interest_rate * borrowed_days / 365). - Implementation computes daily growth and compounds by elapsed full days.
- Anyone can call
trigger_liquidation_auction(owner, vault_id)when vault exceeds liquidation threshold. - Auction contract creates an auction tied to that vault.
- Bidders approve token allowance to auction contract, then call
place_bid. - After end time, call
finalize_auctionon auction contract. - Vault settlement:
settle_liquidation_auction(owner, vault_id).
- Contract owner updates risk params (in percentages) with
set_contract_params:collateral_ratioliquidation_ratiointerest_rateliquidation_feeauction_duration_msmax_oracle_age_ms
- Oracle owner manages reporter access with
set_reporter - Oracle owner commits the active round with
commit_round, optionally using a manual override price
Default params:
- Collateral ratio:
150% - Liquidation ratio:
120% - Interest rate:
5% - Liquidation fee:
1% - Auction duration:
3_600_000milliseconds - Max oracle age:
3_600_000milliseconds
- Vault:
get_vault,get_contract_params,get_oracle_address,get_vaults,get_all_vaults - Oracle:
get_latest_price,get_current_round_summary,is_reporter - Auction:
get_auction,get_active_vault_auction,get_bid,get_all_auctions,get_active_auctions - Token:
balance_of,allowance,total_supply
tusdt-vaultowns the token and auction instances it creates.tusdt-vaultreads collateral pricing from the external oracle contract.- Borrowing mints TUSDT to borrower.
- Repayment and settlement burn TUSDT.