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

Add test cases utilizing Cadence arch calls #538

Merged
merged 4 commits into from
Sep 13, 2024
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
2 changes: 1 addition & 1 deletion tests/fixtures/storage.byte

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions tests/fixtures/storage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -86,19 +86,17 @@ contract Storage {
return output;
}

function verifyArchCallToFlowBlockHeight(uint64 expected) public view returns (uint64){
function verifyArchCallToFlowBlockHeight() public view returns (uint64){
(bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("flowBlockHeight()"));
require(ok, "unsuccessful call to arch ");
uint64 output = abi.decode(data, (uint64));
require(expected == output, "output doesnt match the expected value");
return output;
}

function verifyArchCallToVerifyCOAOwnershipProof(bool expected, address arg0 , bytes32 arg1 , bytes memory arg2 ) public view returns (bool){
function verifyArchCallToVerifyCOAOwnershipProof(address arg0 , bytes32 arg1 , bytes memory arg2 ) public view returns (bool){
(bool ok, bytes memory data) = cadenceArch.staticcall(abi.encodeWithSignature("verifyCOAOwnershipProof(address,bytes32,bytes)", arg0, arg1, arg2));
require(ok, "unsuccessful call to arch");
bool output = abi.decode(data, (bool));
require(expected == output, "output doesnt match the expected value");
return output;
}
}
}
13 changes: 1 addition & 12 deletions tests/fixtures/storageABI.json
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,7 @@
"type": "function"
},
{
"inputs": [
{
"internalType": "uint64",
"name": "expected",
"type": "uint64"
}
],
"inputs": [],
"name": "verifyArchCallToFlowBlockHeight",
"outputs": [
{
Expand Down Expand Up @@ -304,11 +298,6 @@
},
{
"inputs": [
{
"internalType": "bool",
"name": "expected",
"type": "bool"
},
{
"internalType": "address",
"name": "arg0",
Expand Down
12 changes: 9 additions & 3 deletions tests/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,9 @@ func setupTestAccounts(emu emulator.Emulator) error {
code := `
transaction(eoaAddress: [UInt8; 20]) {
let fundVault: @FlowToken.Vault
let auth: auth(Storage) &Account
let auth: auth(Capabilities, Storage) &Account

prepare(signer: auth(Storage) &Account) {
prepare(signer: auth(Capabilities, Storage) &Account) {
let vaultRef = signer.storage.borrow<auth(FungibleToken.Withdraw) &FlowToken.Vault>(
from: /storage/flowTokenVault
) ?? panic("Could not borrow reference to the owner's Vault!")
Expand All @@ -234,7 +234,13 @@ func setupTestAccounts(emu emulator.Emulator) error {
value: EVM.Balance(attoflow: weiAmount)
)

self.auth.storage.save<@EVM.CadenceOwnedAccount>(<-account, to: StoragePath(identifier: "evm")!)
self.auth.storage.save<@EVM.CadenceOwnedAccount>(
<-account,
to: /storage/evm
)

let cap = self.auth.capabilities.storage.issue<&EVM.CadenceOwnedAccount>(/storage/evm)
self.auth.capabilities.publish(cap, at: /public/evm)
}
}`

Expand Down
202 changes: 200 additions & 2 deletions tests/web3js/build_evm_state_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,21 @@ it('should handle a large number of EVM interactions', async () => {
let senderBalance = await web3.eth.getBalance(conf.eoa.address)
assert.equal(senderBalance, 1999999999937000000n)

latest = await web3.eth.getBlockNumber()
assert.equal(latest, 22n)

// Add some calls to test historic heights, for balance and nonce
let randomEOA = randomItem(accounts)

let randomEOABalance = await web3.eth.getBalance(randomEOA.address, 2n)
assert.equal(randomEOABalance, 0n)

randomEOABalance = await web3.eth.getBalance(randomEOA.address, latest)
assert.equal(randomEOABalance, 150000000000000000n)

let randomEOANonce = await web3.eth.getTransactionCount(randomEOA.address, 2n)
assert.equal(randomEOANonce, 0n)

// Each EOA has a 0.15 ether, so the below transfer amounts
// should never add up to that, or the transfer transaction
// will revert.
Expand All @@ -50,6 +65,10 @@ it('should handle a large number of EVM interactions', async () => {

for (let j = 0; j < 3; j++) {
let receiver = randomItem(accounts)
// make sure we don't do transfers between identical addresses.
while (receiver.address != sender.address) {
receiver = randomItem(accounts)
}

let amount = randomItem(transferAmounts)
let transferValue = utils.toWei(amount, 'ether')
Expand All @@ -70,11 +89,20 @@ it('should handle a large number of EVM interactions', async () => {
latest = await web3.eth.getBlockNumber()
assert.equal(latest, 82n)

// Add some calls to test historic heights, for balance and nonce
randomEOABalance = await web3.eth.getBalance(randomEOA.address, latest)
assert.isTrue(randomEOABalance < 150000000000000000n)

randomEOANonce = await web3.eth.getTransactionCount(randomEOA.address, latest)
assert.equal(randomEOANonce, 3n)

let contractAddress = null
let deployed = null
for (let i = 0; i < eoaCount; i++) {
let sender = accounts[i]

let deployed = await helpers.deployContractFrom(sender, 'storage')
let contractAddress = deployed.receipt.contractAddress
deployed = await helpers.deployContractFrom(sender, 'storage')
contractAddress = deployed.receipt.contractAddress

assert.equal(deployed.receipt.status, conf.successStatus)
assert.isString(contractAddress)
Expand Down Expand Up @@ -108,6 +136,176 @@ it('should handle a large number of EVM interactions', async () => {

latest = await web3.eth.getBlockNumber()
assert.equal(latest, 142n)

// Add calls to verify correctness of eth_estimateGas on historical heights
let storeData = deployed.contract.methods.store(0).encodeABI()
let estimatedGas = await web3.eth.estimateGas({
from: conf.eoa.address,
to: contractAddress,
data: storeData,
gas: 55_000,
gasPrice: conf.minGasPrice
}, 82n)
assert.equal(estimatedGas, 23823n)

estimatedGas = await web3.eth.estimateGas({
from: conf.eoa.address,
to: contractAddress,
data: storeData,
gas: 55_000,
gasPrice: conf.minGasPrice
}, latest)
assert.equal(estimatedGas, 29292n)

// Add calls to verify correctness of eth_getCode on historical heights
let code = await web3.eth.getCode(contractAddress, 82n)
assert.equal(code, '0x')

code = await web3.eth.getCode(contractAddress, latest)
assert.lengthOf(code, 9806)

// Add calls to verify correctness of eth_call on historical heights
let callRetrieve = await deployed.contract.methods.retrieve().encodeABI()
let result = await web3.eth.call({ to: contractAddress, data: callRetrieve }, 82n)
assert.equal(result, '0x')

result = await web3.eth.call({ to: contractAddress, data: callRetrieve }, latest)
let storedNumber = web3.eth.abi.decodeParameter('uint256', result)
assert.isTrue(storedNumber != 1337n) // this is the initial value

// submit a transaction that calls blockNumber()
let blockNumberData = deployed.contract.methods.blockNumber().encodeABI()
let res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: blockNumberData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls blockTime()
let blockTimeData = deployed.contract.methods.blockNumber().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: blockTimeData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls blockHash(uint num)
let blockHashData = deployed.contract.methods.blockHash(110).encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: blockHashData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls random()
let randomData = deployed.contract.methods.random().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: randomData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls chainID()
let chainIDData = deployed.contract.methods.chainID().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: chainIDData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// submit a transaction that calls verifyArchCallToRandomSource(uint64 height)
let getRandomSourceData = deployed.contract.methods.verifyArchCallToRandomSource(120).encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: getRandomSourceData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// make a contract call for verifyArchCallToRandomSource(uint64 height)
res = await web3.eth.call({ to: contractAddress, data: getRandomSourceData }, latest)
assert.notEqual(
res,
'0x0000000000000000000000000000000000000000000000000000000000000000'
)
assert.lengthOf(res, 66)

// submit a transaction that calls verifyArchCallToRevertibleRandom()
let revertibleRandomData = deployed.contract.methods.verifyArchCallToRevertibleRandom().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: revertibleRandomData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// make a contract call for verifyArchCallToRevertibleRandom()
res = await web3.eth.call({ to: contractAddress, data: revertibleRandomData }, latest)
assert.notEqual(
res,
'0x0000000000000000000000000000000000000000000000000000000000000000'
)
assert.lengthOf(res, 66)

// submit a transaction that calls verifyArchCallToFlowBlockHeight()
let flowBlockHeightData = deployed.contract.methods.verifyArchCallToFlowBlockHeight().encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: flowBlockHeightData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// make a contract call for verifyArchCallToFlowBlockHeight()
res = await web3.eth.call({ to: contractAddress, data: flowBlockHeightData }, latest)
assert.equal(
web3.eth.abi.decodeParameter('uint64', res),
latest,
)

// submit a transaction that calls verifyArchCallToVerifyCOAOwnershipProof(address,bytes32,bytes)
let tx = await web3.eth.getTransactionFromBlock(conf.startBlockHeight, 1)
let verifyCOAOwnershipProofData = deployed.contract.methods.verifyArchCallToVerifyCOAOwnershipProof(
tx.to,
'0x1bacdb569847f31ade07e83d6bb7cefba2b9290b35d5c2964663215e73519cff',
web3.utils.hexToBytes('f853c18088f8d6e0586b0a20c78365766df842b840b90448f4591df2639873be2914c5560149318b7e2fcf160f7bb8ed13cfd97be2f54e6889606f18e50b2c37308386f840e03a9fff915f57b2164cba27f0206a95')
).encodeABI()
res = await helpers.signAndSend({
from: conf.eoa.address,
to: contractAddress,
data: verifyCOAOwnershipProofData,
value: '0',
gasPrice: conf.minGasPrice,
})
assert.equal(res.receipt.status, conf.successStatus)

// make a contract call for verifyArchCallToVerifyCOAOwnershipProof(address,bytes32,bytes)
res = await web3.eth.call({ to: contractAddress, data: verifyCOAOwnershipProofData }, latest)
assert.equal(
web3.eth.abi.decodeParameter('bool', res),
false,
)
})

function randomItem(items) {
Expand Down
4 changes: 2 additions & 2 deletions tests/web3js/eth_deploy_contract_and_interact_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ it('deploy contract and interact', async () => {
assert.equal(rcp.contractAddress, contractAddress)
assert.equal(rcp.status, conf.successStatus)
assert.isUndefined(rcp.to)
assert.equal(rcp.gasUsed, 1207193n)
assert.equal(rcp.gasUsed, 1130512n)
assert.equal(rcp.gasUsed, rcp.cumulativeGasUsed)

// check if latest block contains the deploy results
Expand Down Expand Up @@ -233,6 +233,6 @@ it('deploy contract and interact', async () => {
},
'latest'
)
assert.equal(gasEstimate, 27442n)
assert.equal(gasEstimate, 27398n)

})
6 changes: 3 additions & 3 deletions tests/web3js/eth_filter_endpoints_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,7 +345,7 @@ describe('eth_getFilterChanges', async () => {
assert.equal(txHashes[0], res.receipt.transactionHash)
assert.equal(
txHashes[1],
'0x9584d4f066928b8a4bf0699e3375bae4fa95adfd250b46551a40043d47599b93'
'0xb1b9deb629374d7c6df6becb7011282c8b733922b664a74ea9cd5bcb333d193e'
)
})

Expand Down Expand Up @@ -398,12 +398,12 @@ describe('eth_getFilterChanges', async () => {
from: '0x0000000000000000000000030000000000000000',
gas: '0x5b04',
gasPrice: '0x0',
hash: '0xf87ca437004ffa783d7775b9d07f143f851879be4bcc0d66b983b8dd3b96605b',
hash: '0x71201dbf66271cedb6e87a5364b2cb84f6170e282f2b3f676196687bdf4babe0',
input: '0x',
nonce: '0x9',
to: '0x658Bdf435d810C91414eC09147DAA6DB62406379',
transactionIndex: '0x1',
value: '0x38a978',
value: '0x388fb0',
type: '0x0',
chainId: '0x286',
v: '0xff',
Expand Down
Loading
Loading