address 0x2 { module Token { struct Coin has store { type: AssetType, value: u64, } // control the minting/creation in the defining module of `ATy` public fun create(type: ATy, value: u64): Coin { Coin { type, value } } public fun value(coin: &Coin): u64 { coin.value } public fun split(coin: Coin, amount: u64): (Coin, Coin) { let other = withdraw(&mut coin, amount); (coin, other) } public fun withdraw(coin: &mut Coin, amount: u64): Coin { assert!(coin.value >= amount, 10); coin.value = coin.value - amount; Coin { type: *&coin.type, value: amount } } public fun join(xus: Coin, coin2: Coin): Coin { deposit(&mut xus, coin2); xus } public fun deposit(coin: &mut Coin, check: Coin) { let Coin { value, type } = check; assert!(&coin.type == &type, 42); coin.value = coin.value + value; } public fun destroy_zero(coin: Coin) { let Coin { value, type: _ } = coin; assert!(value == 0, 11) } } } address 0xB055 { module OneToOneMarket { use std::signer; use 0x2::Token; struct Pool has key { coin: Token::Coin, } struct DepositRecord has key { record: u64, } struct BorrowRecord has key { record: u64, } struct Price has key { price: u64, } fun accept(account: &signer, init: Token::Coin) { let sender = signer::address_of(account); assert!(!exists>(sender), 42); move_to(account, Pool { coin: init }) } public fun register_price( account: &signer, initial_in: Token::Coin, initial_out: Token::Coin, price: u64 ) { let sender = signer::address_of(account); assert!(sender == @0xB055, 42); // assert sender is module writer accept(account, initial_in); accept(account, initial_out); move_to(account, Price { price }) } public fun deposit(account: &signer, coin: Token::Coin) acquires Pool, DepositRecord { let amount = Token::value(&coin); update_deposit_record(account, amount); let pool = borrow_global_mut>(@0xB055); Token::deposit(&mut pool.coin, coin) } public fun borrow( account: &signer, amount: u64, ): Token::Coin acquires Price, Pool, DepositRecord, BorrowRecord { assert!(amount <= max_borrow_amount(account), 1025); update_borrow_record(account, amount); let pool = borrow_global_mut>(@0xB055); Token::withdraw(&mut pool.coin, amount) } fun max_borrow_amount(account: &signer): u64 acquires Price, Pool, DepositRecord, BorrowRecord { let input_deposited = deposited_amount(account); let output_deposited = borrowed_amount(account); let input_into_output = input_deposited * borrow_global>(@0xB055).price; let max_output = if (input_into_output < output_deposited) 0 else (input_into_output - output_deposited); let available_output = { let pool = borrow_global>(@0xB055); Token::value(&pool.coin) }; if (max_output < available_output) max_output else available_output } fun update_deposit_record(account: &signer, amount: u64) acquires DepositRecord { let sender = signer::address_of(account); if (!exists>(sender)) { move_to(account, DepositRecord { record: 0 }) }; let record = &mut borrow_global_mut>(sender).record; *record = *record + amount } fun update_borrow_record(account: &signer, amount: u64) acquires BorrowRecord { let sender = signer::address_of(account); if (!exists>(sender)) { move_to(account, BorrowRecord { record: 0 }) }; let record = &mut borrow_global_mut>(sender).record; *record = *record + amount } fun deposited_amount(account: &signer): u64 acquires DepositRecord { let sender = signer::address_of(account); if (!exists>(sender)) return 0; borrow_global>(sender).record } fun borrowed_amount(account: &signer): u64 acquires BorrowRecord { let sender = signer::address_of(account); if (!exists>(sender)) return 0; borrow_global>(sender).record } } } address 0x70DD { module ToddNickels { use 0x2::Token; use std::signer; struct T has copy, drop, store {} struct Wallet has key { nickels: Token::Coin, } public fun init(account: &signer) { assert!(signer::address_of(account) == @0x70DD, 42); move_to(account, Wallet { nickels: Token::create(T{}, 0) }) } public fun mint(account: &signer): Token::Coin { assert!(signer::address_of(account) == @0x70DD, 42); Token::create(T{}, 5) } public fun destroy(c: Token::Coin) acquires Wallet { Token::deposit(&mut borrow_global_mut(@0x70DD).nickels, c) } } }