Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: operator assignment on array values in boxes #309

Merged
merged 1 commit into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/lib/compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3077,6 +3077,12 @@ export default class Compiler {
const { type, valueType } = storageProp;
const action = type === 'box' && !this.isDynamicType(valueType) ? 'replace' : 'set';

// Honestly not sure why I needed to add this after b89ddc6c24d6102f9e890a0e76222de7e0ca79b5 (0.67.2)
// But it works...
if (type === 'box' && this.teal[this.currentProgram].at(-1)?.teal.startsWith('replace3')) {
this.teal[this.currentProgram].pop();
}

this.handleStorageAction({
node,
name: storageName!,
Expand Down
10 changes: 8 additions & 2 deletions tests/abi.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ async function runMethod(appClient: ApplicationClient, name: string, methodArgs:
let fundAmount = 0;
let callType: 'call' | 'optIn' = 'call';

if (name.includes('Storage') || name.includes('RefAccount')) {
if (name.includes('Storage') || name.includes('RefAccount') || name.includes('InBox')) {
fundAmount = 127_400;
callType = 'optIn';
if (name.includes('Storage') || name.includes('RefAccount')) callType = 'optIn';
}
return commonRunMethod({ appClient, boxes, method: name, methodArgs, fundAmount, callType });
}
Expand Down Expand Up @@ -784,5 +784,11 @@ describe('ABI', function () {

expect(await runMethod(appClient, 'plusEqualsObjValue')).toEqual([3n, 5n]);
});

test('plusEqualsObjValueInBox', async () => {
const { appClient } = await compileAndCreate('plusEqualsObjValueInBox');

expect(await runMethod(appClient, 'plusEqualsObjValueInBox')).toEqual([3n, 5n]);
});
});
});
10 changes: 10 additions & 0 deletions tests/contracts/abi.algo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1252,3 +1252,13 @@ class ABITestPlusEqualsObjValue extends Contract {
return a;
}
}

class ABITestPlusEqualsObjValueInBox extends Contract {
bMap = BoxMap<bytes, { foo: uint64; bar: uint64 }>();

plusEqualsObjValueInBox(): { foo: uint64; bar: uint64 } {
this.bMap('bMap').value = { foo: 3, bar: 4 };
this.bMap('bMap').value.bar += 1;
return this.bMap('bMap').value;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#pragma version 9

// This TEAL was generated by TEALScript v0.67.2
// https://github.com/algorandfoundation/TEALScript

// This contract is compliant with and/or implements the following ARCs: [ ARC4 ]

// The following ten lines of TEAL handle initial program flow
// This pattern is used to make it easy for anyone to parse the start of the program and determine if a specific action is allowed
// Here, action refers to the OnComplete in combination with whether the app is being created or called
// Every possible action for this contract is represented in the switch statement
// If the action is not implmented in the contract, its respective branch will be "NOT_IMPLEMENTED" which just contains "err"
txn ApplicationID
int 0
>
int 6
*
txn OnCompletion
+
switch create_NoOp NOT_IMPLEMENTED NOT_IMPLEMENTED NOT_IMPLEMENTED NOT_IMPLEMENTED NOT_IMPLEMENTED call_NoOp

NOT_IMPLEMENTED:
err

abi_route_plusEqualsObjValueInBox:
// The ABI return prefix
byte 0x151f7c75

// execute plusEqualsObjValueInBox()(uint64,uint64)
callsub plusEqualsObjValueInBox
concat
log
int 1
return

// plusEqualsObjValueInBox()(uint64,uint64)
plusEqualsObjValueInBox:
proto 0 1

// tests/contracts/abi.algo.ts:1260
// this.bMap('bMap').value = { foo: 3, bar: 4 }
byte 0x624d6170 // "bMap"
byte 0x00000000000000030000000000000004
box_put

// tests/contracts/abi.algo.ts:1261
// this.bMap('bMap').value.bar += 1
int 8
byte 0x624d6170 // "bMap"
box_get
assert
extract 8 8
btoi
int 1
+
itob
byte 0x624d6170 // "bMap"
cover 2
box_replace

// tests/contracts/abi.algo.ts:1262
// return this.bMap('bMap').value;
byte 0x624d6170 // "bMap"
box_get
assert
retsub

abi_route_createApplication:
int 1
return

create_NoOp:
method "createApplication()void"
txna ApplicationArgs 0
match abi_route_createApplication
err

call_NoOp:
method "plusEqualsObjValueInBox()(uint64,uint64)"
txna ApplicationArgs 0
match abi_route_plusEqualsObjValueInBox
err
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"hints": {
"plusEqualsObjValueInBox()(uint64,uint64)": {
"call_config": {
"no_op": "CALL"
}
},
"createApplication()void": {
"call_config": {
"no_op": "CREATE"
}
}
},
"bare_call_config": {
"no_op": "NEVER",
"opt_in": "NEVER",
"close_out": "NEVER",
"update_application": "NEVER",
"delete_application": "NEVER"
},
"schema": {
"local": {
"declared": {},
"reserved": {}
},
"global": {
"declared": {},
"reserved": {}
}
},
"state": {
"global": {
"num_byte_slices": 0,
"num_uints": 0
},
"local": {
"num_byte_slices": 0,
"num_uints": 0
}
},
"source": {
"approval": "I3ByYWdtYSB2ZXJzaW9uIDkKCi8vIFRoaXMgVEVBTCB3YXMgZ2VuZXJhdGVkIGJ5IFRFQUxTY3JpcHQgdjAuNjcuMgovLyBodHRwczovL2dpdGh1Yi5jb20vYWxnb3JhbmRmb3VuZGF0aW9uL1RFQUxTY3JpcHQKCi8vIFRoaXMgY29udHJhY3QgaXMgY29tcGxpYW50IHdpdGggYW5kL29yIGltcGxlbWVudHMgdGhlIGZvbGxvd2luZyBBUkNzOiBbIEFSQzQgXQoKLy8gVGhlIGZvbGxvd2luZyB0ZW4gbGluZXMgb2YgVEVBTCBoYW5kbGUgaW5pdGlhbCBwcm9ncmFtIGZsb3cKLy8gVGhpcyBwYXR0ZXJuIGlzIHVzZWQgdG8gbWFrZSBpdCBlYXN5IGZvciBhbnlvbmUgdG8gcGFyc2UgdGhlIHN0YXJ0IG9mIHRoZSBwcm9ncmFtIGFuZCBkZXRlcm1pbmUgaWYgYSBzcGVjaWZpYyBhY3Rpb24gaXMgYWxsb3dlZAovLyBIZXJlLCBhY3Rpb24gcmVmZXJzIHRvIHRoZSBPbkNvbXBsZXRlIGluIGNvbWJpbmF0aW9uIHdpdGggd2hldGhlciB0aGUgYXBwIGlzIGJlaW5nIGNyZWF0ZWQgb3IgY2FsbGVkCi8vIEV2ZXJ5IHBvc3NpYmxlIGFjdGlvbiBmb3IgdGhpcyBjb250cmFjdCBpcyByZXByZXNlbnRlZCBpbiB0aGUgc3dpdGNoIHN0YXRlbWVudAovLyBJZiB0aGUgYWN0aW9uIGlzIG5vdCBpbXBsbWVudGVkIGluIHRoZSBjb250cmFjdCwgaXRzIHJlc3BlY3RpdmUgYnJhbmNoIHdpbGwgYmUgIk5PVF9JTVBMRU1FTlRFRCIgd2hpY2gganVzdCBjb250YWlucyAiZXJyIgp0eG4gQXBwbGljYXRpb25JRAppbnQgMAo+CmludCA2CioKdHhuIE9uQ29tcGxldGlvbgorCnN3aXRjaCBjcmVhdGVfTm9PcCBOT1RfSU1QTEVNRU5URUQgTk9UX0lNUExFTUVOVEVEIE5PVF9JTVBMRU1FTlRFRCBOT1RfSU1QTEVNRU5URUQgTk9UX0lNUExFTUVOVEVEIGNhbGxfTm9PcAoKTk9UX0lNUExFTUVOVEVEOgoJZXJyCgphYmlfcm91dGVfcGx1c0VxdWFsc09ialZhbHVlSW5Cb3g6CgkvLyBUaGUgQUJJIHJldHVybiBwcmVmaXgKCWJ5dGUgMHgxNTFmN2M3NQoKCS8vIGV4ZWN1dGUgcGx1c0VxdWFsc09ialZhbHVlSW5Cb3goKSh1aW50NjQsdWludDY0KQoJY2FsbHN1YiBwbHVzRXF1YWxzT2JqVmFsdWVJbkJveAoJY29uY2F0Cglsb2cKCWludCAxCglyZXR1cm4KCi8vIHBsdXNFcXVhbHNPYmpWYWx1ZUluQm94KCkodWludDY0LHVpbnQ2NCkKcGx1c0VxdWFsc09ialZhbHVlSW5Cb3g6Cglwcm90byAwIDEKCgkvLyB0ZXN0cy9jb250cmFjdHMvYWJpLmFsZ28udHM6MTI2MAoJLy8gdGhpcy5iTWFwKCdiTWFwJykudmFsdWUgPSB7IGZvbzogMywgYmFyOiA0IH0KCWJ5dGUgMHg2MjRkNjE3MCAvLyAiYk1hcCIKCWJ5dGUgMHgwMDAwMDAwMDAwMDAwMDAzMDAwMDAwMDAwMDAwMDAwNAoJYm94X3B1dAoKCS8vIHRlc3RzL2NvbnRyYWN0cy9hYmkuYWxnby50czoxMjYxCgkvLyB0aGlzLmJNYXAoJ2JNYXAnKS52YWx1ZS5iYXIgKz0gMQoJaW50IDgKCWJ5dGUgMHg2MjRkNjE3MCAvLyAiYk1hcCIKCWJveF9nZXQKCWFzc2VydAoJZXh0cmFjdCA4IDgKCWJ0b2kKCWludCAxCgkrCglpdG9iCglieXRlIDB4NjI0ZDYxNzAgLy8gImJNYXAiCgljb3ZlciAyCglib3hfcmVwbGFjZQoKCS8vIHRlc3RzL2NvbnRyYWN0cy9hYmkuYWxnby50czoxMjYyCgkvLyByZXR1cm4gdGhpcy5iTWFwKCdiTWFwJykudmFsdWU7CglieXRlIDB4NjI0ZDYxNzAgLy8gImJNYXAiCglib3hfZ2V0Cglhc3NlcnQKCXJldHN1YgoKYWJpX3JvdXRlX2NyZWF0ZUFwcGxpY2F0aW9uOgoJaW50IDEKCXJldHVybgoKY3JlYXRlX05vT3A6CgltZXRob2QgImNyZWF0ZUFwcGxpY2F0aW9uKCl2b2lkIgoJdHhuYSBBcHBsaWNhdGlvbkFyZ3MgMAoJbWF0Y2ggYWJpX3JvdXRlX2NyZWF0ZUFwcGxpY2F0aW9uCgllcnIKCmNhbGxfTm9PcDoKCW1ldGhvZCAicGx1c0VxdWFsc09ialZhbHVlSW5Cb3goKSh1aW50NjQsdWludDY0KSIKCXR4bmEgQXBwbGljYXRpb25BcmdzIDAKCW1hdGNoIGFiaV9yb3V0ZV9wbHVzRXF1YWxzT2JqVmFsdWVJbkJveAoJZXJy",
"clear": "I3ByYWdtYSB2ZXJzaW9uIDk="
},
"contract": {
"name": "ABITestPlusEqualsObjValueInBox",
"desc": "",
"methods": [
{
"name": "plusEqualsObjValueInBox",
"args": [],
"desc": "",
"returns": {
"type": "(uint64,uint64)",
"desc": ""
}
},
{
"name": "createApplication",
"args": [],
"desc": "",
"returns": {
"type": "void",
"desc": ""
}
}
]
}
}
24 changes: 24 additions & 0 deletions tests/contracts/artifacts/ABITestPlusEqualsObjValueInBox.arc4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"name": "ABITestPlusEqualsObjValueInBox",
"desc": "",
"methods": [
{
"name": "plusEqualsObjValueInBox",
"args": [],
"desc": "",
"returns": {
"type": "(uint64,uint64)",
"desc": ""
}
},
{
"name": "createApplication",
"args": [],
"desc": "",
"returns": {
"type": "void",
"desc": ""
}
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
#pragma version 9