-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ABI Encoding tests. Signed-off-by: ebadiere <[email protected]> * Added blank lines at the end of the contracts. Signed-off-by: ebadiere <[email protected]> --------- Signed-off-by: ebadiere <[email protected]>
- Loading branch information
Showing
5 changed files
with
221 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
// Encoding.sol | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
contract Encoding { | ||
event Added(uint256 result); | ||
|
||
function add(uint256 a, uint256 b) public pure returns (uint256) { | ||
return a + b; | ||
} | ||
|
||
function decodeData(bytes memory encodedData) public pure returns (address, uint256) { | ||
address decodedAddress; | ||
uint256 decodedUint; | ||
assembly { | ||
decodedAddress := mload(add(encodedData, 32)) | ||
decodedUint := mload(add(encodedData, 64)) | ||
} | ||
return (decodedAddress, decodedUint); | ||
} | ||
|
||
function encodeData(address _address, uint256 _uint) public pure returns (bytes memory) { | ||
return abi.encode(_address, _uint); | ||
} | ||
|
||
function encodeAddFunction(uint256 a, uint256 b) public pure returns (bytes memory) { | ||
bytes4 selector = this.add.selector; | ||
|
||
return abi.encodeWithSelector(selector, a, b); | ||
} | ||
|
||
function getPackedData(address _addr, uint256 _amount, string memory _data) public pure returns (bytes memory) { | ||
return abi.encodePacked(_addr, _amount, _data); | ||
} | ||
|
||
function executeAddFunction(uint256 a, uint256 b) public { | ||
bytes memory data = encodeAddFunction(a, b); | ||
(bool success, bytes memory result) = address(this).call(data); | ||
|
||
require(success, "Call failed"); | ||
emit Added(abi.decode(result, (uint256))); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
contract Receiver { | ||
event ReceivedData(uint256 data); | ||
|
||
function receiveData(uint256 data) external { | ||
emit ReceivedData(data); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.20; | ||
|
||
import "./Receiver.sol"; | ||
|
||
contract Sender { | ||
Receiver public receiver; | ||
|
||
constructor(address _receiver) { | ||
receiver = Receiver(_receiver); | ||
} | ||
|
||
function sendDataEncodeWithSignature(uint256 data) public { | ||
bytes memory payload = abi.encodeWithSignature("receiveData(uint256)", data); | ||
|
||
(bool success,) = address(receiver).call(payload); | ||
require(success, "External call using abi.encodeWithSignature failed"); | ||
} | ||
|
||
function sendDataEncodeCall(uint256 data) public { | ||
bytes memory payload = abi.encodeCall( | ||
Receiver(address(receiver)).receiveData, | ||
(data) | ||
); | ||
|
||
(bool success,) = address(receiver).call(payload); | ||
require(success, "External call using abi.encodeCall failed"); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
/*- | ||
* | ||
* Hedera JSON RPC Relay - Hardhat Example | ||
* | ||
* Copyright (C) 2023 Hedera Hashgraph, LLC | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
*/ | ||
const { expect } = require("chai"); | ||
const { ethers } = require("hardhat"); | ||
|
||
describe("@solidityevmequiv Encoding", function() { | ||
let encodingContract, receiver, sender; | ||
|
||
const addressData = "0x1234567890123456789012345678901234567890"; | ||
const uintData = 123456789; | ||
|
||
beforeEach(async function() { | ||
const Encoding = await ethers.getContractFactory("Encoding"); | ||
encodingContract = await Encoding.deploy(); | ||
await encodingContract.deployed(); | ||
|
||
const Receiver = await ethers.getContractFactory("contracts/solidity/encoding/Receiver.sol:Receiver"); | ||
receiver = await Receiver.deploy(); | ||
await receiver.deployed(); | ||
|
||
const Sender = await ethers.getContractFactory("Sender"); | ||
sender = await Sender.deploy(receiver.address); | ||
await sender.deployed(); | ||
|
||
}); | ||
|
||
it("Should decode data", async function() { | ||
const encodedData = ethers.utils.defaultAbiCoder.encode( | ||
["address", "uint256"], | ||
[addressData, uintData] | ||
); | ||
|
||
const result = await encodingContract.decodeData(encodedData); | ||
|
||
expect(result[0]).to.equal(addressData); | ||
expect(result[1]).to.equal(uintData); | ||
}); | ||
|
||
it("Should encode data", async function() { | ||
const result = await encodingContract.encodeData(addressData, uintData); | ||
|
||
const decodedData = ethers.utils.defaultAbiCoder.decode( | ||
["address", "uint256"], | ||
result | ||
); | ||
|
||
expect(decodedData[0]).to.equal(addressData); | ||
expect(decodedData[1]).to.equal(uintData); | ||
}); | ||
|
||
it("Should encode pack data", async function() { | ||
const address = "0x1234567890123456789012345678901234567890"; | ||
const amount = 100; | ||
const data = "Hello, World!"; | ||
|
||
const packedData = encodePacked(address, amount, data); | ||
const result = await encodingContract.getPackedData(address, amount, data); | ||
expect(result).to.equal(packedData); | ||
}); | ||
|
||
it("Should execute the add function and return the correct result to illustrate abi.encodeWitSelector", async function() { | ||
const a = 5; | ||
const b = 7; | ||
|
||
// Verify that the add function returns the correct result | ||
const sum = await encodingContract.add(a, b); | ||
expect(sum).to.equal(a + b); | ||
|
||
// Call the encodeAddFunction | ||
const encodedData = await encodingContract.encodeAddFunction(a, b); | ||
|
||
// Extract the selector and encoded arguments | ||
const selector = encodedData.slice(0, 10); | ||
const encodedArgs = "0x" + encodedData.slice(10); | ||
|
||
// Verify the selector matches the add function's selector | ||
expect(selector).to.equal(encodingContract.interface.getSighash("add")); | ||
|
||
const [decodedA, decodedB] = ethers.utils.defaultAbiCoder.decode(["uint256", "uint256"], encodedArgs); | ||
expect(decodedA).to.equal(a); | ||
expect(decodedB).to.equal(b); | ||
|
||
const tx = await encodingContract.executeAddFunction(a, b); | ||
const receipt = await tx.wait(); | ||
|
||
expect(receipt.events.length).to.equal(1); | ||
expect(receipt.events[0].event).to.equal("Added"); | ||
|
||
const eventResult = receipt.events[0].args[0].toNumber(); | ||
expect(eventResult).to.equal(a + b); | ||
}); | ||
|
||
it("Should call receiveData in Receiver contract via Sender using abi.encodeWithSignature", async function() { | ||
const dataToSend = 12345; | ||
|
||
await expect(sender.sendDataEncodeWithSignature(dataToSend)) | ||
.to.emit(receiver, "ReceivedData") | ||
.withArgs(dataToSend); | ||
}); | ||
|
||
it("Should call receiveData in Receiver contract via Sender using abi.encodeCall", async function() { | ||
const dataToSend = 12345; | ||
|
||
await expect(sender.sendDataEncodeCall(dataToSend)) | ||
.to.emit(receiver, "ReceivedData") | ||
.withArgs(dataToSend); | ||
}); | ||
|
||
|
||
}); | ||
|
||
function encodePacked(address, amount, data) { | ||
const addressBytes = ethers.utils.arrayify(address); | ||
const amountBytes = ethers.utils.zeroPad(ethers.utils.arrayify(amount), 32); | ||
const dataBytes = ethers.utils.toUtf8Bytes(data); | ||
|
||
return ethers.utils.hexConcat([addressBytes, amountBytes, dataBytes]); | ||
} | ||
|