diff --git a/base.json b/base.json deleted file mode 100644 index 2bf27d1..0000000 --- a/base.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "contractTxId": "0NT3T1UHEtMrdUdD0r3B8Mx8rkH5aD-opSSJDqtwHmw", - "depth": 0, - "label": "", - "id": "9f3ba619-44f6-4a50-b7ff-07b345ade647", - "interactions": { - "o-wxRDh27ciT9KpVpB1GAq5TxhrkyNWlBYMhxjMShDE": { - "interactionInput": { - "txId": "o-wxRDh27ciT9KpVpB1GAq5TxhrkyNWlBYMhxjMShDE", - "sortKey": "000000000003,9999999999999,f3648b9ca073a0fe9a2523c8bf516ce729d2b5be79faabaad10ea000b4e85861", - "blockHeight": 3, - "blockTimestamp": 1663344783, - "caller": "NT3I1wgIDXBb1bDaade7lQxKCUy2-ZUOfemrJ884eyQ", - "functionName": "deposit", - "functionArguments": { - "function": "deposit", - "tokenId": "qvLnj9pCRMGiDxcmLAVol3puHbiIP3akL-DfNyCD5u4", - "qty": 1, - "txID": "43qU5V835zbWAO0QOaGAEsXpR5RJ_-eW0rTKM8jqZfM" - }, - "dryWrite": true, - "foreignContractCalls": { - "qvLnj9pCRMGiDxcmLAVol3puHbiIP3akL-DfNyCD5u4": { - "contractTxId": "qvLnj9pCRMGiDxcmLAVol3puHbiIP3akL-DfNyCD5u4", - "depth": 1, - "label": "", - "id": "1e112e20-a42e-400c-bd59-dc23c498ac71", - "interactions": {} - } - } - }, - "interactionOutput": { - "cacheHit": false, - "executionTime": 24, - "valid": true - } - } - } -} \ No newline at end of file diff --git a/docs/INTERNAL_WRITES.md b/docs/INTERNAL_WRITES.md index bfa0e81..ae4747f 100644 --- a/docs/INTERNAL_WRITES.md +++ b/docs/INTERNAL_WRITES.md @@ -63,6 +63,7 @@ Some examples of different types of inner contract writes are available: 1. In the DEX [tutorial](https://academy.warp.cc/tutorials/dex/introduction/intro) 2. The ERC-20 [staking](https://github.com/warp-contracts/wrc/blob/master/examples/staking/src/actions/staking.rs#L35) example. 3. In the integration [tests](https://github.com/warp-contracts/warp/tree/main/src/__tests__/integration/internal-writes) of the inner writes feature. +4. In the [staking example](https://github.com/warp-contracts/wrc/tree/master/examples/staking#-staking) of the ERC-20 token standard. **NOTE** Do not overuse the inner writes feature - as it can quickly make the debugging and contracts' interaction analysis very difficult. ### Security @@ -76,6 +77,11 @@ The id of the calling contract can be obtained from `SmartWeave.caller`. and option to set gas limits gives the best security. ### Example inner write call flow + +#### Stage I - preparing inner write transaction + + +#### Stage II - Contract `Contract B` makes an internal write on contract `Contract A` at interaction `i(n)`. **(1)** Evaluator loads the state of the `Contract A` up to internal write interaction `i(n)`. diff --git a/src/__tests__/integration/data/aftr/pstInitState.json b/src/__tests__/integration/data/aftr/pstInitState.json index a4324dc..2462dbc 100644 --- a/src/__tests__/integration/data/aftr/pstInitState.json +++ b/src/__tests__/integration/data/aftr/pstInitState.json @@ -46,4 +46,4 @@ "" ] ] - } \ No newline at end of file + } diff --git a/src/__tests__/integration/data/aftr/sampleContractInitState.json b/src/__tests__/integration/data/aftr/sampleContractInitState.json index 6db7e65..23c5f79 100644 --- a/src/__tests__/integration/data/aftr/sampleContractInitState.json +++ b/src/__tests__/integration/data/aftr/sampleContractInitState.json @@ -23,4 +23,4 @@ [ "communityLogo", ""], [ "evolve", null ] ] -} \ No newline at end of file +} diff --git a/src/__tests__/integration/internal-writes/internal-write-callee.test.ts b/src/__tests__/integration/internal-writes/internal-write-callee.test.ts index b27df4d..ad7c42a 100644 --- a/src/__tests__/integration/internal-writes/internal-write-callee.test.ts +++ b/src/__tests__/integration/internal-writes/internal-write-callee.test.ts @@ -279,7 +279,7 @@ describe('Testing internal writes', () => { }); }); - fdescribe('with internal writes throwing exceptions', () => { + describe('with internal writes throwing exceptions', () => { beforeAll(async () => { await deployContracts(); }); diff --git a/src/contract/HandlerBasedContract.ts b/src/contract/HandlerBasedContract.ts index 7047414..c9a21d4 100644 --- a/src/contract/HandlerBasedContract.ts +++ b/src/contract/HandlerBasedContract.ts @@ -104,8 +104,6 @@ export class HandlerBasedContract implements Contract { callingInteraction.interactionInput.foreignContractCalls[_contractTxId] = callStack; this._callStack = callStack; this._rootSortKey = _parentContract.rootSortKey; - - // console.log('==== CHILD constructor, parent callstack: ', _parentContract.getCallStack().print()); } else { this._callDepth = 0; this._callStack = new ContractCallStack(_contractTxId, 0); @@ -336,9 +334,6 @@ export class HandlerBasedContract implements Contract { // {name: 'InternalWrite', value: callingContractTxId} const handlerResult = await this.callContract(input, undefined, undefined, tags, transfer, strict); - if ((input as any).function === 'deposit') { - // console.log('====== handlerResult ======', handlerResult); - } if (strict && handlerResult.type !== 'ok') { throw Error(`Cannot create interaction: ${handlerResult.errorMessage}`); } @@ -347,11 +342,6 @@ export class HandlerBasedContract implements Contract { this.logger.debug('Input', input); this.logger.debug('Callstack', callStack.print()); - if ((input as any).function === 'deposit') { - // console.log('====== Call stack ======', callStack.print()); - // console.log('====== Inner Writes ======', innerWrites); - } - innerWrites.forEach((contractTxId) => { tags.push({ name: SmartWeaveTags.INTERACT_WRITE, @@ -640,16 +630,6 @@ export class HandlerBasedContract implements Contract { const executionContext = await this.createExecutionContextFromTx(this._contractTxId, interactionTx); const evalStateResult = await this.warp.stateEvaluator.eval(executionContext, currentTx); - // there could haven been some earlier, non-cached interactions - which will be added - // after eval in line 619. We need to clear them, as it is only the currently - // being added interaction that we're interested in. - /*if (this._parentContract) { - console.log('======== CLEARING CALL STACK'); - const callStack = new ContractCallStack(this.txId(), this._callDepth); - const callingInteraction = this._parentContract.getCallStack().getInteraction(this._callingInteraction.id); - callingInteraction.interactionInput.foreignContractCalls[this.txId()] = callStack; - this._callStack = callStack; - }*/ this.logger.debug('callContractForTx - evalStateResult', { result: evalStateResult.cachedValue.state, txId: this._contractTxId @@ -666,7 +646,6 @@ export class HandlerBasedContract implements Contract { currentTx }; - // console.log('====== evalInteraction'); const result = await this.evalInteraction( interactionData, executionContext, @@ -683,16 +662,7 @@ export class HandlerBasedContract implements Contract { executionContext: ExecutionContext>, evalStateResult: EvalStateResult ) { - // console.log('====== addInteractionData to callStack', interactionData.interaction.input); - // console.log('====== addInteractionData to callStack - callstack', this.getCallStack().print()); - // console.log('====== addInteractionData to callStack - parent callstack', this.parent()?.getCallStack().print()); - const interactionCall: InteractionCall = this.getCallStack().addInteractionData(interactionData); - - // console.log('====== AFTER ADDING ======'); - // console.log('====== addInteractionData to callStack - callstack', this.getCallStack().print()); - // console.log('====== addInteractionData to callStack - parent callstack', this.parent()?.getCallStack().print()); - const benchmark = Benchmark.measure(); const result = await executionContext.handler.handle( executionContext, @@ -700,8 +670,6 @@ export class HandlerBasedContract implements Contract { interactionData ); - // console.log('RESULT', result); - interactionCall.update({ cacheHit: false, outputState: this._evaluationOptions.stackTrace.saveState ? result.state : undefined, @@ -711,9 +679,6 @@ export class HandlerBasedContract implements Contract { gasUsed: result.gasUsed }); - // console.log('==== Callstack after interaction call', this.getCallStack().print()); - // console.log('==== PARENT Callstack after interaction call', this.parent()?.getCallStack().print()); - return result; } diff --git a/src/core/Warp.ts b/src/core/Warp.ts index 59a72a1..c6668a5 100644 --- a/src/core/Warp.ts +++ b/src/core/Warp.ts @@ -1,6 +1,6 @@ import Arweave from 'arweave'; import { LevelDbCache } from '../cache/impl/LevelDbCache'; -import {Contract, InnerCallData, InnerCallType} from '../contract/Contract'; +import { Contract, InnerCallData, InnerCallType } from '../contract/Contract'; import { CreateContract } from '../contract/deploy/CreateContract'; import { DefaultCreateContract } from '../contract/deploy/impl/DefaultCreateContract'; import { HandlerBasedContract } from '../contract/HandlerBasedContract'; @@ -58,11 +58,7 @@ export class Warp { * @param contractTxId * @param callingContract */ - contract( - contractTxId: string, - callingContract?: Contract, - innerCallData?: InnerCallData - ): Contract { + contract(contractTxId: string, callingContract?: Contract, innerCallData?: InnerCallData): Contract { return new HandlerBasedContract(contractTxId, this, callingContract, innerCallData); }