Even more interesting one, deploying contract and do static init in both init and body. The code should increment the counter twice, once in init and once in body (because of the call). The value written to storage address 0x20 in the first contract is the value read from the other contract’s transient storage, i.e. a message has been passed between contracts without using return.
{
(def "T_INIT_ADDR" 0x00)
(def "T_COUNTER_ADDR" 0x20)
(def "tInit" (TLOAD (ADDRESS) T_INIT_ADDR))
(def "tCounter" (TLOAD (ADDRESS) T_COUNTER_ADDR))
(def "tInitW" (val) (TSTORE T_INIT_ADDR val))
(def "tCounterW" (val) (TSTORE T_COUNTER_ADDR val))
(def "StaticInit"
(unless tInit {
(tInitW 0x01)
(tCounterW 0x00)
})
)
[0x20] (create {
StaticInit
(tCounterW (+ tCounter 1))
(returnlll {
StaticInit
(tCounterW (+ tCounter 1))
(return 0)
})
})
(msg @0x20 0)
[[0x00]] (TLOAD @0x20 T_COUNTER_ADDR)
}
The contract with address 0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6
is the deploying one, using the default contract address for evm invocations like these. The one being deployed is 5ecfbe86fcd903321c505cb5c8a5de6331e2e7b1
.
{
"errno": 0,
"errpc": 64,
"returnData": "",
"mem": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ecfbe86fcd903321c505cb5c8a5de6331e2e7b1296000396000f300fe6000305c601157600160005d600060205d5b60016020305c0160205d600060005260206000f30000000000000000000000000000000000",
"stack": [],
"accounts": [
{
"address": "cd1722f2947def4cf144679da39c4c32bdc35681",
"balance": "0",
"nonce": 1,
"code": "",
"storage": [],
"destroyed": false
},
{
"address": "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"balance": "0",
"nonce": 1,
"code": "6000600052596000526050806042600051396000516000f060205260006000526020600060206000600060205160155a03f1506000515060206020515c60005500fe6000305c601157600160005d600060205d5b60016020305c0160205d60278060296000396000f300fe6000305c601157600160005d600060205d5b60016020305c0160205d600060005260206000f300",
"storage": [
{
"address": "0",
"value": "2"
}
],
"destroyed": false
},
{
"address": "5ecfbe86fcd903321c505cb5c8a5de6331e2e7b1",
"balance": "0",
"nonce": 0,
"code": "6000305c601157600160005d600060205d5b60016020305c0160205d600060005260206000f300",
"storage": [],
"destroyed": false
}
],
"logs": []
}
Here’s an even more advanced one. The first contract writes a message into its transient storage then calls the other. The other contract looks at the transient storage of (CALLER) to see if they left them a message. If so, and if it’s the correct one, it will respond. The first contract checks the targets transient storage after the call and writes the response into its regular storage.
{
(def "T_INIT_ADDR" 0x00)
(def "T_MSG_ADDR" 0x20)
(def "tInit" (TLOAD (ADDRESS) T_INIT_ADDR))
(def "tMsg" (TLOAD (ADDRESS) T_MSG_ADDR))
(def "tInitW" (val) (TSTORE T_INIT_ADDR val))
(def "tMsgW" (val) (TSTORE T_MSG_ADDR val))
(def "StaticInit"
(unless tInit {
(tInitW 0x01)
(tMsgW 0x00)
})
)
[0x20] (create {
StaticInit
(returnlll {
StaticInit
(when (= (TLOAD (CALLER) T_MSG_ADDR) "Here's ur message.") (tMsgW "Thanks, bro."))
(return 0)
})
})
(tMsgW "Here's ur message.")
(msg @0x20 0)
[[0x00]] (TLOAD @0x20 T_MSG_ADDR)
}
andreas@AndreasLT:~/solevm/bin$ node run.js
{
"errno": 0,
"errpc": 101,
"returnData": "",
"mem": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000005ecfbe86fcd903321c505cb5c8a5de6331e2e7b16000305c601157600160005d600060205d5b7f486572652773207572206d6573736167652e00000000000000000000000000006020335c14156060577f5468616e6b732c2062726f2e000000000000000000000000000000000000000060205d5b600060005260206000f3000000000000000000000000000000000000000000",
"stack": [],
"accounts": [
{
"address": "cd1722f2947def4cf144679da39c4c32bdc35681",
"balance": "0",
"nonce": 1,
"code": "",
"storage": [],
"destroyed": false
},
{
"address": "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6",
"balance": "0",
"nonce": 1,
"code": "600060005259600052608c80610067600051396000516000f06020527f486572652773207572206d6573736167652e000000000000000000000000000060205d60006000526020600060206000600060205160155a03f1506000515060206020515c60005500fe6000305c601157600160005d600060205d5b606c806100206000396000f300fe6000305c601157600160005d600060205d5b7f486572652773207572206d6573736167652e00000000000000000000000000006020335c14156060577f5468616e6b732c2062726f2e000000000000000000000000000000000000000060205d5b600060005260206000f300",
"storage": [
{
"address": "0",
"value": "5468616e6b732c2062726f2e0000000000000000000000000000000000000000"
}
],
"destroyed": false
},
{
"address": "5ecfbe86fcd903321c505cb5c8a5de6331e2e7b1",
"balance": "0",
"nonce": 0,
"code": "6000305c601157600160005d600060205d5b7f486572652773207572206d6573736167652e00000000000000000000000000006020335c14156060577f5468616e6b732c2062726f2e000000000000000000000000000000000000000060205d5b600060005260206000f300",
"storage": [],
"destroyed": false
}
],
"logs": []
}