Skip to content

Commit

Permalink
Merge branch 'main' into ud/fix-race-condition
Browse files Browse the repository at this point in the history
  • Loading branch information
Unique-Divine authored May 31, 2024
2 parents 64ed0a2 + f881f82 commit b8132f8
Show file tree
Hide file tree
Showing 15 changed files with 369 additions and 98 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/proto-lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
# timeout-minutes: 5
# steps:
# - uses: actions/checkout@v4
# - uses: bufbuild/[email protected].1
# - uses: bufbuild/[email protected].2
# - uses: bufbuild/buf-lint-action@v1
# with:
# input: "proto"
Expand All @@ -31,7 +31,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: bufbuild/[email protected].1
- uses: bufbuild/[email protected].2
with:
github_token: ${{ github.token }}
- uses: bufbuild/buf-breaking-action@v1
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- [#1887](https://github.com/NibiruChain/nibiru/pull/1887) - test(evm): eth api integration test suite
- [#1889](https://github.com/NibiruChain/nibiru/pull/1889) - feat: implemented basic evm tx methods
- [#1895](https://github.com/NibiruChain/nibiru/pull/1895) - refactor(geth): Reference go-ethereum as a submodule for easier change tracking with upstream
- [#1901](https://github.com/NibiruChain/nibiru/pull/1901) - test(evm): more e2e test contracts for edge cases

#### Dapp modules: perp, spot, oracle, etc

Expand Down Expand Up @@ -115,7 +116,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Bump `github.com/hashicorp/go-getter` from 1.7.1 to 1.7.4 ([#1858](https://github.com/NibiruChain/nibiru/pull/1858))
- Bump `github.com/btcsuite/btcd` from 0.23.3 to 0.24.0 ([#1862](https://github.com/NibiruChain/nibiru/pull/1862))
- Bump `pozetroninc/github-action-get-latest-release` from 0.7.0 to 0.8.0 ([#1863](https://github.com/NibiruChain/nibiru/pull/1863))
- Bump `bufbuild/buf-setup-action` from 1.30.1 to 1.32.1 ([#1891](https://github.com/NibiruChain/nibiru/pull/1891))
- Bump `bufbuild/buf-setup-action` from 1.30.1 to 1.32.2 ([#1891](https://github.com/NibiruChain/nibiru/pull/1891), [#1900](https://github.com/NibiruChain/nibiru/pull/1900))

## [v1.3.0](https://github.com/NibiruChain/nibiru/releases/tag/v1.3.0) - 2024-05-07

Expand Down
30 changes: 22 additions & 8 deletions e2e/evm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,28 @@ npm test
> [email protected] test
> jest

PASS test/evm.test.js (13.163 s)
Ethereum JSON-RPC Interface Tests
✓ Simple Transfer, balance check (4258 ms)
✓ Smart Contract (8656 ms)

Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
PASS test/contract_infinite_loop_gas.test.js (8.617 s)
Infinite loop gas contract
✓ should fail due to out of gas error (4152 ms)

PASS test/contract_send_nibi.test.js (16.977 s)
Send NIBI from smart contract
✓ send nibi via "sendViaTransfer" method (4244 ms)
✓ send nibi via "sendViaSend" method (4239 ms)
✓ send nibi via "sendViaCall" method (4259 ms)

PASS test/erc20.test.js (8.845 s)
ERC-20 contract tests
✓ send, balanceOf (8765 ms)

PASS test/basic_queries.test.js
Basic Queries
✓ Simple transfer, balance check (4224 ms)

Test Suites: 4 passed, 4 total
Tests: 6 passed, 6 total
Snapshots: 0 total
Time: 13.187 s, estimated 14 s
Time: 38.783 s, estimated 50 s
Ran all test suites.

```
17 changes: 17 additions & 0 deletions e2e/evm/contracts/InfiniteLoopGas.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract InifiniteLoopGas {
uint256 public counter = 0;

// Using up all of the gas that you send causes your transaction to fail.
// State changes are undone.
// Gas spent are not refunded.
function forever() public {
// Here we run a loop until all of the gas are spent
// and the transaction fails
while (true) {
counter += 1;
}
}
}
31 changes: 31 additions & 0 deletions e2e/evm/contracts/InfiniteLoopGasCompiled.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"_format": "hh-sol-artifact-1",
"contractName": "InifiniteLoopGas",
"sourceName": "contracts/InfiniteLoopGas.sol",
"abi": [
{
"inputs": [],
"name": "counter",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "forever",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
],
"bytecode": "0x60806040526000805534801561001457600080fd5b5061015e806100246000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806361bc221a1461003b5780639ff9a60314610059575b600080fd5b610043610063565b60405161005091906100aa565b60405180910390f35b610061610069565b005b60005481565b5b60011561008f57600160008082825461008391906100f4565b9250508190555061006a565b565b6000819050919050565b6100a481610091565b82525050565b60006020820190506100bf600083018461009b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006100ff82610091565b915061010a83610091565b9250828201905080821115610122576101216100c5565b5b9291505056fea2646970667358221220946d430ff7d8c16c5401d4156ff1b5d75c112460fbba0fb343581bd3c86cfe1c64736f6c63430008180033",
"deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806361bc221a1461003b5780639ff9a60314610059575b600080fd5b610043610063565b60405161005091906100aa565b60405180910390f35b610061610069565b005b60005481565b5b60011561008f57600160008082825461008391906100f4565b9250508190555061006a565b565b6000819050919050565b6100a481610091565b82525050565b60006020820190506100bf600083018461009b565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006100ff82610091565b915061010a83610091565b9250828201905080821115610122576101216100c5565b5b9291505056fea2646970667358221220946d430ff7d8c16c5401d4156ff1b5d75c112460fbba0fb343581bd3c86cfe1c64736f6c63430008180033",
"linkReferences": {},
"deployedLinkReferences": {}
}
32 changes: 32 additions & 0 deletions e2e/evm/contracts/ReceiveNibiCompiled.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"_format": "hh-sol-artifact-1",
"contractName": "ReceiveNibi",
"sourceName": "contracts/SendReceiveNibi.sol",
"abi": [
{
"stateMutability": "payable",
"type": "fallback"
},
{
"inputs": [],
"name": "getBalance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"stateMutability": "payable",
"type": "receive"
}
],
"bytecode": "0x608060405234801561001057600080fd5b5060bb8061001f6000396000f3fe608060405260043610601f5760003560e01c806312065fe0146027576025565b36602557005b005b348015603257600080fd5b506039604d565b60405160449190606c565b60405180910390f35b600047905090565b6000819050919050565b6066816055565b82525050565b6000602082019050607f6000830184605f565b9291505056fea2646970667358221220f4ee193ceac7d6ffbf8d62d675a1d21fed9c154b8e9407c7aba0f7301ef0db6b64736f6c63430008180033",
"deployedBytecode": "0x608060405260043610601f5760003560e01c806312065fe0146027576025565b36602557005b005b348015603257600080fd5b506039604d565b60405160449190606c565b60405180910390f35b600047905090565b6000819050919050565b6066816055565b82525050565b6000602082019050607f6000830184605f565b9291505056fea2646970667358221220f4ee193ceac7d6ffbf8d62d675a1d21fed9c154b8e9407c7aba0f7301ef0db6b64736f6c63430008180033",
"linkReferences": {},
"deployedLinkReferences": {}
}
50 changes: 50 additions & 0 deletions e2e/evm/contracts/SendNibiCompiled.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
{
"_format": "hh-sol-artifact-1",
"contractName": "SendNibi",
"sourceName": "contracts/SendReceiveNibi.sol",
"abi": [
{
"inputs": [
{
"internalType": "address payable",
"name": "_to",
"type": "address"
}
],
"name": "sendViaCall",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "_to",
"type": "address"
}
],
"name": "sendViaSend",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address payable",
"name": "_to",
"type": "address"
}
],
"name": "sendViaTransfer",
"outputs": [],
"stateMutability": "payable",
"type": "function"
}
],
"bytecode": "0x608060405234801561001057600080fd5b50610390806100206000396000f3fe6080604052600436106100345760003560e01c8063636e082b1461003957806374be480614610055578063830c29ae14610071575b600080fd5b610053600480360381019061004e919061026a565b61008d565b005b61006f600480360381019061006a919061026a565b6100d7565b005b61008b6004803603810190610086919061026a565b610154565b005b8073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156100d3573d6000803e3d6000fd5b5050565b60008173ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050905080610150576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610147906102f4565b60405180910390fd5b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163460405161017b90610345565b60006040518083038185875af1925050503d80600081146101b8576040519150601f19603f3d011682016040523d82523d6000602084013e6101bd565b606091505b509150915081610202576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f9906102f4565b60405180910390fd5b505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102378261020c565b9050919050565b6102478161022c565b811461025257600080fd5b50565b6000813590506102648161023e565b92915050565b6000602082840312156102805761027f610207565b5b600061028e84828501610255565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f2073656e64204e69626900000000000000000000000000600082015250565b60006102de601383610297565b91506102e9826102a8565b602082019050919050565b6000602082019050818103600083015261030d816102d1565b9050919050565b600081905092915050565b50565b600061032f600083610314565b915061033a8261031f565b600082019050919050565b600061035082610322565b915081905091905056fea26469706673582212201fcd9f47953315963ca2a2687073914cbb3f29161100cec83979926b96714b2b64736f6c63430008180033",
"deployedBytecode": "0x6080604052600436106100345760003560e01c8063636e082b1461003957806374be480614610055578063830c29ae14610071575b600080fd5b610053600480360381019061004e919061026a565b61008d565b005b61006f600480360381019061006a919061026a565b6100d7565b005b61008b6004803603810190610086919061026a565b610154565b005b8073ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f193505050501580156100d3573d6000803e3d6000fd5b5050565b60008173ffffffffffffffffffffffffffffffffffffffff166108fc349081150290604051600060405180830381858888f19350505050905080610150576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610147906102f4565b60405180910390fd5b5050565b6000808273ffffffffffffffffffffffffffffffffffffffff163460405161017b90610345565b60006040518083038185875af1925050503d80600081146101b8576040519150601f19603f3d011682016040523d82523d6000602084013e6101bd565b606091505b509150915081610202576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016101f9906102f4565b60405180910390fd5b505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006102378261020c565b9050919050565b6102478161022c565b811461025257600080fd5b50565b6000813590506102648161023e565b92915050565b6000602082840312156102805761027f610207565b5b600061028e84828501610255565b91505092915050565b600082825260208201905092915050565b7f4661696c656420746f2073656e64204e69626900000000000000000000000000600082015250565b60006102de601383610297565b91506102e9826102a8565b602082019050919050565b6000602082019050818103600083015261030d816102d1565b9050919050565b600081905092915050565b50565b600061032f600083610314565b915061033a8261031f565b600082019050919050565b600061035082610322565b915081905091905056fea26469706673582212201fcd9f47953315963ca2a2687073914cbb3f29161100cec83979926b96714b2b64736f6c63430008180033",
"linkReferences": {},
"deployedLinkReferences": {}
}
51 changes: 51 additions & 0 deletions e2e/evm/contracts/SendReceiveNibi.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

contract ReceiveNibi {
/*
Which function is called, fallback() or receive()?
send Nibi
|
msg.data is empty?
/ \
yes no
/ \
receive() exists? fallback()
/ \
yes no
/ \
receive() fallback()
*/

// Function to receive Nibi. msg.data must be empty
receive() external payable {}

// Fallback function is called when msg.data is not empty
fallback() external payable {}

function getBalance() public view returns (uint256) {
return address(this).balance;
}
}

contract SendNibi {
function sendViaTransfer(address payable _to) public payable {
// This function is no longer recommended for sending Nibi.
_to.transfer(msg.value);
}

function sendViaSend(address payable _to) public payable {
// Send returns a boolean value indicating success or failure.
// This function is not recommended for sending Nibi.
bool sent = _to.send(msg.value);
require(sent, "Failed to send Nibi");
}

function sendViaCall(address payable _to) public payable {
// Call returns a boolean value indicating success or failure.
// This is the current recommended method to use.
(bool sent, bytes memory data) = _to.call{value : msg.value}("");
require(sent, "Failed to send Nibi");
}
}
3 changes: 2 additions & 1 deletion e2e/evm/jest.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module.exports = {
testEnvironment: 'node',
testMatch: ['**/test/**/*.js'],
testMatch: ['**/test/**/*.test.js'],
verbose: true,
"maxWorkers": 1
};
36 changes: 36 additions & 0 deletions e2e/evm/test/basic_queries.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const {ethers} = require('ethers')
const {account, provider, deployContract} = require('./setup')

describe('Basic Queries', () => {

it('Simple transfer, balance check', async () => {
const randomAddress = ethers.Wallet.createRandom().address
const amountToSend = 1000n // unibi
const gasLimit = 100_000n // unibi

const senderBalanceBefore = await provider.getBalance(account.address)
const recipientBalanceBefore = await provider.getBalance(randomAddress)

expect(senderBalanceBefore).toBeGreaterThan(0)
expect(recipientBalanceBefore).toEqual(0n)

// Execute EVM transfer
const transaction = {
gasLimit: gasLimit,
to: randomAddress,
value: amountToSend
}
const txResponse = await account.sendTransaction(transaction)
await txResponse.wait()
expect(txResponse).toHaveProperty('blockHash')

const senderBalanceAfter = await provider.getBalance(account.address)
const recipientBalanceAfter = await provider.getBalance(randomAddress)

// TODO: https://github.com/NibiruChain/nibiru/issues/1902
// gas is not deducted regardless the gas limit, check this
const expectedSenderBalance = senderBalanceBefore - amountToSend
expect(senderBalanceAfter).toBeLessThanOrEqual(expectedSenderBalance)
expect(recipientBalanceAfter).toEqual(amountToSend)
}, 20_000)
})
24 changes: 24 additions & 0 deletions e2e/evm/test/contract_infinite_loop_gas.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const {deployContract} = require('./setup')

describe('Infinite loop gas contract', () => {
let contract

beforeAll(async () => {
contract = await deployContract('InfiniteLoopGasCompiled.json')
})

it('should fail due to out of gas error', async () => {
const initialCounter = await contract.counter()
expect(initialCounter).toBe(0n)

try {
const tx = await contract.forever({gasLimit: 1000000})
await tx.wait()
fail("The transaction should have failed but did not.")
} catch (error) {
expect(error.message).toContain("transaction execution reverted")
}
const finalCounter = await contract.counter()
expect(finalCounter).toEqual(initialCounter)
}, 20000)
})
37 changes: 37 additions & 0 deletions e2e/evm/test/contract_send_nibi.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const {ethers} = require('ethers')
const {account, provider, deployContract} = require('./setup')

let contract

const doContractSend = async (sendMethod) => {
const recipientAddress = ethers.Wallet.createRandom().address
const transferValue = 100n * 10n ** 6n // NIBI

const ownerBalanceBefore = await provider.getBalance(account.address) // NIBI
const recipientBalanceBefore = await provider.getBalance(recipientAddress) // NIBI
expect(recipientBalanceBefore).toEqual(0n)

const tx = await contract[sendMethod](recipientAddress, {value: transferValue})
await tx.wait()

const ownerBalanceAfter = await provider.getBalance(account.address) // NIBI
const recipientBalanceAfter = await provider.getBalance(recipientAddress) // NIBI

expect(ownerBalanceAfter).toBeLessThanOrEqual(ownerBalanceBefore - transferValue)
expect(recipientBalanceAfter).toEqual(transferValue)
}

describe('Send NIBI from smart contract', () => {

beforeAll(async () => {
contract = await deployContract('SendNibiCompiled.json')
})

it.each([
['sendViaTransfer'],
['sendViaSend'],
['sendViaCall'],
])('send nibi via %p method', async (sendMethod) => {
await doContractSend(sendMethod)
}, 20000);
})
32 changes: 32 additions & 0 deletions e2e/evm/test/erc20.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
const {ethers} = require('ethers')
const {account, deployContract} = require('./setup')

describe('ERC-20 contract tests', () => {

it('send, balanceOf', async () => {
const contract = await deployContract('FunTokenCompiled.json')
const contractAddress = await contract.getAddress()
expect(contractAddress).toBeDefined()

// Execute contract: ERC20 transfer
const shrimpAddress = ethers.Wallet.createRandom().address
let ownerInitialBalance = ethers.parseUnits("1000000", 18)

const amountToSend = ethers.parseUnits("1000", 18) // contract tokens

let ownerBalance = await contract.balanceOf(account.address)
let shrimpBalance = await contract.balanceOf(shrimpAddress)

expect(ownerBalance).toEqual(ownerInitialBalance)
expect(shrimpBalance).toEqual(ethers.toBigInt(0))

let tx = await contract.transfer(shrimpAddress, amountToSend)
await tx.wait()

ownerBalance = await contract.balanceOf(account.address)
shrimpBalance = await contract.balanceOf(shrimpAddress)

expect(ownerBalance).toEqual(ownerInitialBalance - amountToSend)
expect(shrimpBalance).toEqual(amountToSend)
}, 20000)
})
Loading

0 comments on commit b8132f8

Please sign in to comment.