From 5a91e0a9116ac18c5a8c030f1158291ff489989d Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 12 Apr 2023 08:56:54 +0200 Subject: [PATCH 1/6] [vm test] balance and transfer --- assembly/__tests__/env-coins.spec.ts | 65 ++++++++++++++++++++++++++++ vm-mock/vm.js | 50 +++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 assembly/__tests__/env-coins.spec.ts diff --git a/assembly/__tests__/env-coins.spec.ts b/assembly/__tests__/env-coins.spec.ts new file mode 100644 index 00000000..0fadbe8a --- /dev/null +++ b/assembly/__tests__/env-coins.spec.ts @@ -0,0 +1,65 @@ +// This file is aim to test the env coins related functions which are external functions + +import { env } from '../env'; +import { resetStorage } from '../vm-mock'; +import { Address, Storage } from '../std'; +import { stringToBytes } from '@massalabs/as-types'; + +const testAddress = new Address( + 'AU12E6N5BFAdC2wyiBV6VJjqkWhpz1kLVp2XpbRdSnL1mKjCWT6oR', +); + +const testAddress2 = new Address( + 'AU12E6N5BFAdC2wyiBV6VJjqkWhpz1kLVp2XpbRdSnL1mKjCWT6oT', +); + +beforeEach(() => { + resetStorage(); +}); + +describe('Testing env coins related functions', () => { + test('Testing transferCoins (assembly_script_transfer_coins)', () => { + const amount: u64 = 100; + const receiverCurrentBalance = env.balanceOf(testAddress.toString()); + // given + expect(receiverCurrentBalance).toBe(0); + // when + env.transferCoins(testAddress.toString(), amount); + // then + expect(env.balanceOf(testAddress.toString())).toBe(amount); + }); + + test('Testing transferCoinsOf (assembly_script_transfer_coins_for)', () => { + const amount: u64 = 100; + env.transferCoins(testAddress.toString(), amount); + const emitterCurrentBalance = env.balanceOf(testAddress.toString()); + const receiverCurrentBalance = env.balanceOf(testAddress2.toString()); + + // given + expect(emitterCurrentBalance).toBeGreaterThanOrEqual(amount); + expect(receiverCurrentBalance).toBe(0); + // when + env.transferCoinsOf( + testAddress.toString(), + testAddress2.toString(), + amount, + ); + // then + expect(env.balanceOf(testAddress2.toString())).toBe(amount); + }); + + test('Testing balanceOf (assembly_script_balance_of)', () => { + const amount: u64 = 100; + // given + expect(env.balanceOf(testAddress.toString())).toBe(0); + // when + env.transferCoins(testAddress.toString(), amount); + // then + expect(env.balanceOf(testAddress.toString())).toBe(amount); + }); + + test('Testing balance (assembly_script_balance)', () => { + // The balance of the current contract is 100000 + expect(env.balance()).toBe(100000); + }); +}); diff --git a/vm-mock/vm.js b/vm-mock/vm.js index fdb06a86..76c19afc 100644 --- a/vm-mock/vm.js +++ b/vm-mock/vm.js @@ -49,6 +49,7 @@ let callStack = callerAddress + ' , ' + contractAddress; "key2" : "value2" }, "Contract" : "./pathOfTheAssemblyScriptContract", + "Balance" : "100000 } } */ @@ -62,10 +63,12 @@ function resetLedger() { ledger.set(callerAddress, { storage: new Map(), contract: '', + balance: 100000, }); ledger.set(contractAddress, { storage: new Map(), contract: '', + balance: 100000, }); } @@ -489,6 +492,53 @@ export default function createMockedABI( const addressLedger = ledger.get(a); return newArrayBuffer(addressLedger.contract); }, + + assembly_script_transfer_coins(_addressPtr, _coinsAmount) { + const address = ptrToString(_addressPtr); + if (!ledger.has(address)) { + ledger.set(address, { + storage: new Map(), + contract: '', + balance: 0, + }); + } + ledger.get(address).balance += Number(_coinsAmount); + }, + + assembly_script_transfer_coins_for( + _addressFromPtr, + _addressToPtr, + _coinsAmount, + ) { + const addressFrom = ptrToString(_addressFromPtr); + const addressTo = ptrToString(_addressToPtr); + + if (!ledger.has(addressFrom)) { + throw new Error( + `Address ${addressFrom} does not exist in the ledger.`, + ); + } + if (!ledger.has(addressTo)) { + ledger.set(addressTo, { + storage: new Map(), + contract: '', + balance: 0, + }); + } + ledger.get(addressFrom).balance -= Number(_coinsAmount); + ledger.get(addressTo).balance += Number(_coinsAmount); + }, + + assembly_script_get_balance() { + return BigInt(ledger.get(contractAddress).balance); + }, + + assembly_script_get_balance_for(aPtr) { + const a = ptrToString(aPtr); + if (!ledger.has(a)) return BigInt(0); + + return BigInt(ledger.get(a).balance); + }, }, }; From eeef0ed3da1ca088f9bbbf2092deb3977d38f506 Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 12 Apr 2023 09:19:14 +0200 Subject: [PATCH 2/6] [vm test] callCoins --- assembly/__tests__/env-coins.spec.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/assembly/__tests__/env-coins.spec.ts b/assembly/__tests__/env-coins.spec.ts index 0fadbe8a..0d851d5f 100644 --- a/assembly/__tests__/env-coins.spec.ts +++ b/assembly/__tests__/env-coins.spec.ts @@ -62,4 +62,9 @@ describe('Testing env coins related functions', () => { // The balance of the current contract is 100000 expect(env.balance()).toBe(100000); }); + + test('Testing callCoins (assembly_script_get_call_coins)', () => { + // We don't have a way to set the call coins yet in the mock + expect(env.callCoins()).toBe(0); + }); }); From bb683c281f25b5e3a28e276954cd46154f88708c Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 12 Apr 2023 14:26:55 +0200 Subject: [PATCH 3/6] [vm test] change balance number to bigInt --- vm-mock/vm.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/vm-mock/vm.js b/vm-mock/vm.js index 76c19afc..f0671b24 100644 --- a/vm-mock/vm.js +++ b/vm-mock/vm.js @@ -63,12 +63,12 @@ function resetLedger() { ledger.set(callerAddress, { storage: new Map(), contract: '', - balance: 100000, + balance: BigInt(100000), }); ledger.set(contractAddress, { storage: new Map(), contract: '', - balance: 100000, + balance: BigInt(100000), }); } @@ -499,10 +499,11 @@ export default function createMockedABI( ledger.set(address, { storage: new Map(), contract: '', - balance: 0, + balance: BigInt(0), }); } - ledger.get(address).balance += Number(_coinsAmount); + ledger.get(callerAddress).balance -= BigInt(_coinsAmount); + ledger.get(address).balance += BigInt(_coinsAmount); }, assembly_script_transfer_coins_for( @@ -522,11 +523,15 @@ export default function createMockedABI( ledger.set(addressTo, { storage: new Map(), contract: '', - balance: 0, + balance: BigInt(0), }); } - ledger.get(addressFrom).balance -= Number(_coinsAmount); - ledger.get(addressTo).balance += Number(_coinsAmount); + try { + ledger.get(addressFrom).balance -= BigInt(_coinsAmount); + ledger.get(addressTo).balance += BigInt(_coinsAmount); + } catch (error) { + console.log(error); + } }, assembly_script_get_balance() { From 251ec9478a5d39ceb68672abd4a98602382337d1 Mon Sep 17 00:00:00 2001 From: Ben Date: Thu, 13 Apr 2023 19:25:56 +0200 Subject: [PATCH 4/6] [vm test] improve test title --- assembly/__tests__/env-coins.spec.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assembly/__tests__/env-coins.spec.ts b/assembly/__tests__/env-coins.spec.ts index 0d851d5f..e81e13a6 100644 --- a/assembly/__tests__/env-coins.spec.ts +++ b/assembly/__tests__/env-coins.spec.ts @@ -18,7 +18,7 @@ beforeEach(() => { }); describe('Testing env coins related functions', () => { - test('Testing transferCoins (assembly_script_transfer_coins)', () => { + it('transferCoins', () => { const amount: u64 = 100; const receiverCurrentBalance = env.balanceOf(testAddress.toString()); // given @@ -29,7 +29,7 @@ describe('Testing env coins related functions', () => { expect(env.balanceOf(testAddress.toString())).toBe(amount); }); - test('Testing transferCoinsOf (assembly_script_transfer_coins_for)', () => { + it('transferCoins of another address', () => { const amount: u64 = 100; env.transferCoins(testAddress.toString(), amount); const emitterCurrentBalance = env.balanceOf(testAddress.toString()); @@ -48,7 +48,7 @@ describe('Testing env coins related functions', () => { expect(env.balanceOf(testAddress2.toString())).toBe(amount); }); - test('Testing balanceOf (assembly_script_balance_of)', () => { + it('get the balance of an address', () => { const amount: u64 = 100; // given expect(env.balanceOf(testAddress.toString())).toBe(0); @@ -58,12 +58,12 @@ describe('Testing env coins related functions', () => { expect(env.balanceOf(testAddress.toString())).toBe(amount); }); - test('Testing balance (assembly_script_balance)', () => { + it('get the balance of the current address', () => { // The balance of the current contract is 100000 expect(env.balance()).toBe(100000); }); - test('Testing callCoins (assembly_script_get_call_coins)', () => { + it('callCoins', () => { // We don't have a way to set the call coins yet in the mock expect(env.callCoins()).toBe(0); }); From 904a55101ddbfc96dd8f0bdedef7bedc960860a3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 13 Apr 2023 17:29:54 +0000 Subject: [PATCH 5/6] Update README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 901f0806..c783ac5b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ # Massa-as-sdk -![check-code-coverage](https://img.shields.io/badge/coverage-75%25-orange) +![check-code-coverage](https://img.shields.io/badge/coverage-76%25-orange) + Massa-as-sdk is a collection of tools, objects, and functions specifically designed for Massa smart contracts in AssemblyScript. This SDK enables you to import object classes, such as address and storage objects, and use them without having to write them from scratch every time. Additionally, it allows you to use Massa's ABI functions. From 558d9fa0025a42e0282117f6ed7afd61459dafe7 Mon Sep 17 00:00:00 2001 From: Ben Date: Fri, 14 Apr 2023 09:25:12 +0200 Subject: [PATCH 6/6] [vm test] improve coins tests --- assembly/__tests__/env-coins.spec.ts | 7 ++++++- vm-mock/vm.js | 22 +++++++++++++++++----- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/assembly/__tests__/env-coins.spec.ts b/assembly/__tests__/env-coins.spec.ts index e81e13a6..1f9ab705 100644 --- a/assembly/__tests__/env-coins.spec.ts +++ b/assembly/__tests__/env-coins.spec.ts @@ -14,14 +14,18 @@ const testAddress2 = new Address( ); beforeEach(() => { + // We set the balance of the current contract to 100000 in the resetStorage resetStorage(); }); describe('Testing env coins related functions', () => { it('transferCoins', () => { const amount: u64 = 100; + // The sender is the current contract executing the transfer + const senderBalance = env.balance(); const receiverCurrentBalance = env.balanceOf(testAddress.toString()); // given + expect(senderBalance).toBe(100000); expect(receiverCurrentBalance).toBe(0); // when env.transferCoins(testAddress.toString(), amount); @@ -31,10 +35,11 @@ describe('Testing env coins related functions', () => { it('transferCoins of another address', () => { const amount: u64 = 100; + // we first transfer coins to the emitter address env.transferCoins(testAddress.toString(), amount); + const emitterCurrentBalance = env.balanceOf(testAddress.toString()); const receiverCurrentBalance = env.balanceOf(testAddress2.toString()); - // given expect(emitterCurrentBalance).toBeGreaterThanOrEqual(amount); expect(receiverCurrentBalance).toBe(0); diff --git a/vm-mock/vm.js b/vm-mock/vm.js index f0671b24..06a756df 100644 --- a/vm-mock/vm.js +++ b/vm-mock/vm.js @@ -502,6 +502,12 @@ export default function createMockedABI( balance: BigInt(0), }); } + const callerBalance = ledger.get(callerAddress).balance; + if (callerBalance < BigInt(_coinsAmount)) { + throw new Error( + `Not enough balance to transfer ${_coinsAmount} coins.`, + ); + } ledger.get(callerAddress).balance -= BigInt(_coinsAmount); ledger.get(address).balance += BigInt(_coinsAmount); }, @@ -519,6 +525,7 @@ export default function createMockedABI( `Address ${addressFrom} does not exist in the ledger.`, ); } + if (!ledger.has(addressTo)) { ledger.set(addressTo, { storage: new Map(), @@ -526,12 +533,17 @@ export default function createMockedABI( balance: BigInt(0), }); } - try { - ledger.get(addressFrom).balance -= BigInt(_coinsAmount); - ledger.get(addressTo).balance += BigInt(_coinsAmount); - } catch (error) { - console.log(error); + + const addressFromBalance = ledger.get(addressFrom).balance; + + if (addressFromBalance < BigInt(_coinsAmount)) { + throw new Error( + `Not enough balance to transfer ${_coinsAmount} coins.`, + ); } + + ledger.get(addressFrom).balance -= BigInt(_coinsAmount); + ledger.get(addressTo).balance += BigInt(_coinsAmount); }, assembly_script_get_balance() {