diff --git a/README.md b/README.md index 42b3789..ce516b1 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ and test suites. New code coming in regularly. toggle ping->pong, and only one other address is authorized to toggle pong->ping. _Checking sender address_, _Comparing sender address with another arbitrary address_ +- **Bank** : A simple contract can receive coins, and store them into a cell. + _receive TON_, _store TON in a smart contract_ ```sh yarn @@ -47,4 +49,7 @@ yarn test tests/PingPong.spec.ts # Only test ping pong 2 yarn test tests/PingPong2.spec.ts + +# Only test bank +yarn test tests/Bank.spec.ts ``` diff --git a/contracts/bank.fc b/contracts/bank.fc index 4a87f8a..5b0676b 100644 --- a/contracts/bank.fc +++ b/contracts/bank.fc @@ -1,56 +1,52 @@ #include "imports/stdlib.fc"; ;; storage variables -global int ctx_balance; +global cell ctx_balance; () load_data() impure { - var ds = get_data().begin_parse(); - ctx_balance = ds~load_uint(32); - ds.end_parse(); + var ds = get_data().begin_parse(); + ctx_balance = ds~load_ref(); + ds.end_parse(); } -() save_data() impure { - set_data( +() save_data(int coins) impure { + set_data( + begin_cell() + .store_ref( begin_cell() - .store_uint(ctx_balance, 32) - .end_cell() - ); + .store_coins(coins) + .end_cell() + ) + .end_cell() + ); } () recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure { - if (in_msg_body.slice_empty?()) { - return (); - } - - slice cs = in_msg_full.begin_parse(); - int flags = cs~load_uint(4); - if (flags & 1) { - return (); - } - - load_data(); - ~strdump("balance"); - ~dump(ctx_balance); - - int coins_amount = in_msg_body~load_coins(); - ~strdump("coins_amount"); - ~dump(coins_amount); - - if (coins_amount != 0) { - ~strdump("not zero"); - ctx_balance += coins_amount; - ~strdump("newbalance"); - ~dump(ctx_balance); - save_data(); - return (); - } - - load_data(); + if (in_msg_body.slice_empty?()) { + return (); + } + + slice cs = in_msg_full.begin_parse(); + int flags = cs~load_uint(4); + if (flags & 1) { + return (); + } + load_data(); + slice current = ctx_balance.begin_parse(); + (_, int current_balance) = current.load_coins(); + + int coins_amount = in_msg_body~load_coins(); + + if (coins_amount != 0) { + save_data(coins_amount + current_balance); return (); + } + + throw(0xffff); } -int get_bal() method_id { - load_data(); - return ctx_balance; +cell get_bal() method_id { + load_data(); + return ctx_balance; } diff --git a/tests/Bank.spec.ts b/tests/Bank.spec.ts index b1f40c0..d66cde2 100644 --- a/tests/Bank.spec.ts +++ b/tests/Bank.spec.ts @@ -1,6 +1,6 @@ import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox'; import '@ton/test-utils'; -import { Cell, toNano, ContractProvider } from '@ton/core'; +import { Cell, toNano } from '@ton/core'; import { compile } from '@ton/blueprint'; import { Bank } from '../wrappers/Bank'; @@ -19,38 +19,40 @@ describe('[Bank]', () => { code = await compile('Bank'); blockchain = await Blockchain.create(); user1 = await blockchain.treasury('user1'); - bankContract = blockchain.openContract( - Bank.createFromConfig({ balance: 0 }, code) - ); - for (let i = 0; i < 3; i += 1) { + bankContract = blockchain.openContract(Bank.createFromConfig(code)); + for (let i = 0; i < 10; i += 1) { transfers.push({ sender: user1 as unknown as SandboxContract, - coins: toNano(BigInt(Math.round(Math.random() * 100))), + coins: BigInt(Math.round(Math.random() * 100)), }); } + /* + smart contract balance goes + above the 1B limit + */ + transfers.push({ + sender: user1 as unknown as SandboxContract, + coins: BigInt('1000000000'), + }); }); it('[Bank] user1 transfers to smart contract', async () => { - const deployResult = await bankContract.sendDeploy( + await bankContract.sendDeploy( (user1 as SandboxContract).getSender(), toNano('0.05') ); - let i = 1; + let bi = 0n; for (const transfer of transfers) { - console.log('transfer.coins'); - console.log(transfer.coins); - /* const balance = await bankContract.getBalance(); - console.log('balance', balance); */ - const bal = await bankContract.getBal(); - console.log('bal', bal); - const a = await bankContract.sendTransfer( + bi += transfer.coins; + await bankContract.sendTransfer( (user1 as SandboxContract).getSender(), { value: toNano('0.05'), coins: transfer.coins, } ); - expect(true).toBe(true); + const bal = await bankContract.getBal(); + expect(bal).toBe(bi); } }); }); diff --git a/wrappers/Bank.ts b/wrappers/Bank.ts index c4d163c..c37e93e 100644 --- a/wrappers/Bank.ts +++ b/wrappers/Bank.ts @@ -10,12 +10,10 @@ import { toNano, } from '@ton/core'; -export type BankConfig = { - balance: number; -}; - -export function bankConfigToCell(config: BankConfig): Cell { - return beginCell().storeUint(config.balance, 32).endCell(); +export function bankConfigToCell(): Cell { + return beginCell() + .storeRef(beginCell().storeCoins(toNano('0')).endCell()) + .endCell(); } export class Bank implements Contract { @@ -28,8 +26,8 @@ export class Bank implements Contract { return new Bank(address); } - static createFromConfig(config: BankConfig, code: Cell, workchain = 0) { - const data = bankConfigToCell(config); + static createFromConfig(Cell, workchain = 0) { + const data = bankConfigToCell(); const init = { code, data }; return new Bank(contractAddress(workchain, init), init); } @@ -62,11 +60,6 @@ export class Bank implements Contract { async getBal(provider: ContractProvider) { const result = await provider.get('get_bal', []); - return result.stack.readNumber(); - } - - async getBalance(provider: ContractProvider) { - const result = await provider.get('get_balance', []); - return result.stack.readNumber(); + return result.stack.readCell().beginParse().preloadCoins(); } }