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

Tests for Address operations #458

Merged
merged 2 commits into from
Oct 18, 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
67 changes: 67 additions & 0 deletions contracts/solidity/address/Address.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

contract AddressContract {
receive() external payable {}
string message = "Hello World from AddressContract!";
event emitMessage(string a);
event res(bool answer, bytes data);

function getAddressBalance(address addressToQuery) external view returns (uint256) {
return addressToQuery.balance;
}

function getAddressCode(address addressToQuery) external view returns (bytes memory) {
return addressToQuery.code;
}

function getAddressCodeHash(address addressToQuery) external view returns (bytes32) {
return addressToQuery.codehash;
}

function transferTo(address payable addressToQuery, uint amount) external {
return addressToQuery.transfer(amount);
}

function sendTo(address payable addressToQuery, uint amount) external {
bool answer = addressToQuery.send(amount);
require(answer, "Error sending");
}

function callAddr(address payable addressToQuery, uint amount) external {
(bool answer,) = addressToQuery.call{value: amount}("");
require(answer, "Error calling");
}

function callAddrWithSig(address payable addressToQuery, uint amount, string memory functionSig) external payable returns (bytes memory){
(bool answer, bytes memory data) = addressToQuery.call{gas: 900000, value: amount}(abi.encodeWithSignature(functionSig));
require(answer, "Error calling");
emit res(answer, data);

return data;
}

function delegate(address payable addressToQuery, string memory functionSig) external payable returns (bytes memory){
(bool success, bytes memory data) = addressToQuery.delegatecall{gas: 90000000}(abi.encodeWithSignature(functionSig));
require(success, "Error calling");
emit res(success, data);

return data;
}

function staticCall(address payable addressToQuery, string memory functionSig) external payable returns (bytes memory){
(bool answer, bytes memory data) = addressToQuery.staticcall(abi.encodeWithSignature(functionSig));
require(answer, "Error calling");
emit res(answer, data);

return data;
}

function staticCallSet(address payable addressToQuery, string memory functionSig, uint number) external payable returns (bytes memory){
(bool answer, bytes memory data) = addressToQuery.staticcall(abi.encodeWithSignature(functionSig, number));
require(answer, "Error calling");
emit res(answer, data);

return data;
}
}
30 changes: 30 additions & 0 deletions contracts/solidity/address/Recipient.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

contract Recipient {
receive() external payable {}
event msgValue(uint256 value);
event emitMessage(string message);
string message = "Hello World from Recipient contract!";
uint myNumber = 5;

function getNumber() external view returns (uint) {
return myNumber;
}

function setNumber(uint number) external returns (uint) {
return myNumber = number;
}

function getMessageValue() external payable {
emit msgValue(msg.value);
}

function helloWorldMessage() external {
emit emitMessage(message);
}

fallback() external payable {

}
}
2 changes: 2 additions & 0 deletions test/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ const Contract = {
Transaction: 'Transaction',
MessageFrameAddresses: 'MessageFrameAddresses',
New: 'New',
AddressContract: 'AddressContract',
Recipient: 'Recipient',
}

const CALL_EXCEPTION = 'CALL_EXCEPTION'
Expand Down
146 changes: 146 additions & 0 deletions test/solidity/address/address.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
const { expect } = require('chai')
const { ethers } = require('hardhat')
const Constants = require('../../constants')
const Utils = require('../../hts-precompile/utils')

const TOP_UP_AMOUNT = ethers.utils.parseEther('1.0');
const TRANSFER_AMOUNT = 1

describe('Solidity Address tests:', function () {
let signers,contract, wallet, walletAddr, recipientContract, recipientAddr;

const tinybarToWeibar = (amount) => amount.mul(Utils.tinybarToWeibarCoef)
const weibarTotinybar = (amount) => amount.div(Utils.tinybarToWeibarCoef)

before(async function () {
signers = await ethers.getSigners()
wallet = signers[0];
walletAddr = await wallet.getAddress()

//deploy test contract
const factory = await ethers.getContractFactory(Constants.Contract.AddressContract)
contract = await factory.deploy()
await contract.deployed();

//deploy test contract
const calledFactory = await ethers.getContractFactory(Constants.Contract.Recipient)
recipientContract = await calledFactory.deploy()
await recipientContract.deployed();
recipientAddr = await recipientContract.address;

//top up the test contract with some funds
let tx = {
to: contract.address,
value: TOP_UP_AMOUNT
}
const topUpRes = await wallet.sendTransaction(tx)
topUpRes.wait();
})

it('should verify solidity functionality: <address>.balance', async function () {
const balance = await wallet.getBalance();
const res = await contract.getAddressBalance(walletAddr);

expect(tinybarToWeibar(res)).to.equal(balance);
Nana-EC marked this conversation as resolved.
Show resolved Hide resolved
expect(tinybarToWeibar(res).gt(0)).to.be.true;
})

it('should verify solidity functionality: <address>.code', async function () {
const walletAddrCodeRes = await contract.getAddressCode(walletAddr);
const contractAddrCodeRes = await contract.getAddressCode(contract.address);

expect(walletAddrCodeRes).to.exist;
expect(walletAddrCodeRes).to.equal('0x');
expect(contractAddrCodeRes).to.exist;
expect(contractAddrCodeRes).to.not.equal('0x');
expect(contractAddrCodeRes.length > 2).to.be.true;
})

it('should verify solidity functionality: <address>.codehash', async function () {
const walletAddrCodeRes = await contract.getAddressCode(walletAddr);
const contractAddrCodeRes = await contract.getAddressCode(contract.address);
const hashedWalletCode = ethers.utils.keccak256(walletAddrCodeRes);
const hashedContractCode = ethers.utils.keccak256(contractAddrCodeRes);
const walletAddrResHash = await contract.getAddressCodeHash(walletAddr);
const contractAddrResHash = await contract.getAddressCodeHash(contract.address);

expect(hashedWalletCode).to.equal(walletAddrResHash);
expect(hashedContractCode).to.equal(contractAddrResHash);
})

it('should verify solidity functionality: <address payable>.transfer', async function () {
const recipientBalanceInitial = await ethers.provider.getBalance(recipientAddr);

const tx = await contract.transferTo(recipientAddr, TRANSFER_AMOUNT);
await tx.wait();

const recipientBalanceFinal = await ethers.provider.getBalance(recipientAddr);
const diff = recipientBalanceFinal.sub(recipientBalanceInitial)

expect(weibarTotinybar(diff)).to.equal(TRANSFER_AMOUNT);
expect(recipientBalanceInitial.lt(recipientBalanceFinal)).to.be.true;
})

it('should verify solidity functionality: <address payable>.send', async function () {
const recipientBalanceInitial = await ethers.provider.getBalance(recipientAddr);

const tx = await contract.sendTo(recipientAddr, TRANSFER_AMOUNT);
await tx.wait();

const recipientBalanceFinal = await ethers.provider.getBalance(recipientAddr);
const diff = recipientBalanceFinal.sub(recipientBalanceInitial)

expect(weibarTotinybar(diff)).to.equal(TRANSFER_AMOUNT);
expect(recipientBalanceInitial.lt(recipientBalanceFinal)).to.be.true;
})

it('should verify solidity functionality: <address>.call', async function () {
const recipientBalanceInitial = await ethers.provider.getBalance(recipientAddr);

const tx = await contract.callAddr(recipientAddr, TRANSFER_AMOUNT);
await tx.wait();

const recipientBalanceFinal = await ethers.provider.getBalance(recipientAddr);
const diff = recipientBalanceFinal.sub(recipientBalanceInitial)

expect(weibarTotinybar(diff)).to.equal(TRANSFER_AMOUNT);
expect(recipientBalanceInitial.lt(recipientBalanceFinal)).to.be.true;
})

it('should verify solidity functionality: <address>.call -> with function signature', async function () {
const resTx = await contract.callAddrWithSig(recipientAddr, TRANSFER_AMOUNT, "getMessageValue()");
const receipt = await resTx.wait();
const data = receipt.events[0].data;
const value = BigInt(data);

expect(value).to.equal(TRANSFER_AMOUNT);
})

it('should verify solidity functionality: <address>.delegatecall', async function () {
const MESSAGE_FROM_ADDRESS = "Hello World from AddressContract!";
const resTx = await contract.delegate(recipientAddr, "helloWorldMessage()");
const receipt = await resTx.wait();
const message = receipt.events[0].args[0];

expect(message).to.equal(MESSAGE_FROM_ADDRESS);
})

it('should verify solidity functionality: <address>.staticcall', async function () {
const MY_NUMBER = 5;
const resTx = await contract.staticCall(recipientAddr, "getNumber()");
const receipt = await resTx.wait();
const result = receipt.events[0].args[1];
const myNumber = BigInt(result);

expect(myNumber).to.equal(MY_NUMBER);
})

it('should verify solidity functionality: <address>.staticcall -> Try to set state', async function () {
try {
const resTx = await contract.staticCallSet(recipientAddr, "setNumber(uint number)", 10);
await resTx.wait();
} catch (error) {
expect(error.code).to.equal('CALL_EXCEPTION');
}
})
})
Loading