Skip to content

Commit

Permalink
Add basic fee currency test
Browse files Browse the repository at this point in the history
  • Loading branch information
palango committed Nov 27, 2023
1 parent 1ae96ce commit 16fe6b3
Show file tree
Hide file tree
Showing 9 changed files with 868 additions and 25 deletions.
484 changes: 484 additions & 0 deletions contracts/celo/abigen/MockSortedOracles.go

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions contracts/celo/celo.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import _ "embed"
//go:generate go run ../../cmd/abigen --pkg abigen --out abigen/SortedOracles.go --abi compiled/SortedOracles.abi --type SortedOracles
//go:generate go run ../../cmd/abigen --pkg abigen --out abigen/FeeCurrencyWhitelist.go --abi compiled/FeeCurrencyWhitelist.abi --type FeeCurrencyWhitelist
//go:generate go run ../../cmd/abigen --pkg abigen --out abigen/FeeCurrency.go --abi compiled/FeeCurrency.abi --type FeeCurrency
//go:generate go run ../../cmd/abigen --pkg abigen --out abigen/MockSortedOracles.go --abi compiled/MockSortedOracles.abi --type MockSortedOracles

//go:embed compiled/CeloRegistry.bin-runtime
var RegistryBytecodeRaw []byte
Expand All @@ -20,6 +21,9 @@ var ProxyBytecodeRaw []byte
//go:embed compiled/SortedOracles.bin-runtime
var SortedOraclesBytecodeRaw []byte

//go:embed compiled/MockSortedOracles.bin-runtime
var MockSortedOraclesBytecodeRaw []byte

//go:embed compiled/FeeCurrencyWhitelist.bin-runtime
var FeeCurrencyWhitelistBytecodeRaw []byte

Expand Down
226 changes: 226 additions & 0 deletions contracts/celo/compiled/MockSortedOracles.abi
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
[
{
"inputs": [],
"name": "DENOMINATOR",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "addOracle",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "isOldestReportExpired",
"outputs": [
{
"internalType": "bool",
"name": "",
"type": "bool"
},
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "token",
"type": "address"
}
],
"name": "medianRate",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "medianTimestamp",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "numRates",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "numTimestamps",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "numerators",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "removeExpiredReports",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "removeOracle",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "uint256",
"name": "",
"type": "uint256"
},
{
"internalType": "address",
"name": "",
"type": "address"
},
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "report",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
1 change: 1 addition & 0 deletions contracts/celo/compiled/MockSortedOracles.bin-runtime
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
0x608060405234801561001057600080fd5b50600436106100c95760003560e01c8063bbc66a9411610081578063f0ca4adb1161005b578063f0ca4adb1461017d578063f7ca69631461018b578063ffe736bf146101ab57600080fd5b8063bbc66a941461012f578063dd34ca3b14610143578063ef90e1b01461015557600080fd5b80636dd6ef0c116100b25780636dd6ef0c146100ce57806380e507441461010a578063918f86741461011e57600080fd5b8063071b48fc146100ce57806353a57297146100f5575b600080fd5b6100e26100dc366004610277565b50600090565b6040519081526020015b60405180910390f35b610108610103366004610299565b505050565b005b6101086101183660046102d5565b50505050565b6100e269d3c21bcecceda100000081565b6100e261013d366004610277565b50600190565b610108610151366004610322565b5050565b610168610163366004610277565b6101ef565b604080519283526020830191909152016100ec565b61010861015136600461034c565b6100e2610199366004610277565b60006020819052908152604090205481565b6101c36101b9366004610277565b5060009061ce1090565b60408051921515835273ffffffffffffffffffffffffffffffffffffffff9091166020830152016100ec565b6000807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff31ea73ffffffffffffffffffffffffffffffffffffffff841601610243575069d3c21bcecceda1000000928392509050565b506000928392509050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461027257600080fd5b919050565b60006020828403121561028957600080fd5b6102928261024e565b9392505050565b6000806000606084860312156102ae57600080fd5b6102b78461024e565b92506102c56020850161024e565b9150604084013590509250925092565b600080600080608085870312156102eb57600080fd5b6102f48561024e565b9350602085013592506103096040860161024e565b91506103176060860161024e565b905092959194509250565b6000806040838503121561033557600080fd5b61033e8361024e565b946020939093013593505050565b6000806040838503121561035f57600080fd5b6103688361024e565b91506103766020840161024e565b9050925092905056fea164736f6c6343000813000a
2 changes: 1 addition & 1 deletion contracts/celo/compiled/SortedOracles.bin-runtime

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion contracts/celo/compiled/update.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ CONTRACTS_DIR=${CELO_OPTIMISM_REPO:-~/optimism}/packages/contracts-bedrock

(cd "$CONTRACTS_DIR" && forge build)

for contract in GoldToken CeloRegistry SortedOracles FeeCurrencyWhitelist FeeCurrency Proxy AddressSortedLinkedListWithMedian
for contract in GoldToken CeloRegistry SortedOracles FeeCurrencyWhitelist FeeCurrency Proxy AddressSortedLinkedListWithMedian MockSortedOracles
do
contract_json="$CONTRACTS_DIR/forge-artifacts/$contract.sol/$contract.json"
jq .abi "$contract_json" > "$SCRIPT_DIR/$contract.abi"
Expand Down
129 changes: 129 additions & 0 deletions core/blockchain_celo_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

package core

import (
"math/big"
"testing"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/ethash"
fee_currencies "github.com/ethereum/go-ethereum/contracts"
contracts "github.com/ethereum/go-ethereum/contracts/celo"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)

// TestNativeTransferWithFeeCurrency tests the following:
//
// 1. A transaction whose gasFeeCap is greater than the baseFee is valid.
// 2. Gas accounting for celo fee currency transactions is correct.
// 3. Only the transaction's tip will be received by the coinbase.
// 4. The transaction sender pays for both the tip and baseFee.
// 5. The base fee goes to the fee handler.
func TestNativeTransferWithFeeCurrency(t *testing.T) {
testNativeTransferWithFeeCurrency(t, rawdb.HashScheme)
testNativeTransferWithFeeCurrency(t, rawdb.PathScheme)
}

func testNativeTransferWithFeeCurrency(t *testing.T, scheme string) {
var (
aa = common.HexToAddress("0x000000000000000000000000000000000000aaaa")
engine = ethash.NewFaker()

// A sender who makes transactions, has some funds
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
config = *params.AllEthashProtocolChanges
funds = DevBalance
gspec = &Genesis{
Config: &config,
Alloc: celoGenesisAccounts(addr1),
}
)
gspec.Config.Cel2Time = uint64ptr(0)

signer := types.LatestSigner(gspec.Config)

_, blocks, _ := GenerateChainWithGenesis(gspec, engine, 1, func(i int, b *BlockGen) {
b.SetCoinbase(common.Address{1})

txdata := &types.CeloDynamicFeeTx{
ChainID: gspec.Config.ChainID,
Nonce: 0,
To: &aa,
Gas: 100000,
GasFeeCap: newGwei(5),
GasTipCap: big.NewInt(2),
Data: []byte{},
FeeCurrency: &FeeCurrencyAddr,
}
tx := types.NewTx(txdata)
tx, _ = types.SignTx(tx, signer, key1)

b.AddTx(tx)
})
chain, err := NewBlockChain(rawdb.NewMemoryDatabase(), DefaultCacheConfigWithScheme(scheme), gspec, nil, engine, vm.Config{}, nil, nil)
if err != nil {
t.Fatalf("failed to create tester chain: %v", err)
}
defer chain.Stop()

if n, err := chain.InsertChain(blocks); err != nil {
t.Fatalf("block %d: failed to insert into chain: %v", n, err)
}

block := chain.GetBlockByNumber(1)

// 1+2: Ensure correct gas amount is deducted
expectedGas := uint64(71000)
if block.GasUsed() != expectedGas {
t.Fatalf("incorrect amount of gas spent: expected %d, got %d", expectedGas, block.GasUsed())
}

state, _ := chain.State()

backend := CeloBackend{
chainConfig: chain.chainConfig,
state: state,
}
actual, _ := fee_currencies.GetBalanceOf(&backend, block.Coinbase(), FeeCurrencyAddr)

// 3: Ensure that miner received only the tx's tip.
expected := new(big.Int).SetUint64(block.GasUsed() * block.Transactions()[0].GasTipCap().Uint64())
if actual.Cmp(expected) != 0 {
t.Fatalf("miner balance incorrect: expected %d, got %d", expected, actual)
}

// 4: Ensure the tx sender paid for the gasUsed * (tip + block baseFee).
actual, _ = fee_currencies.GetBalanceOf(&backend, addr1, FeeCurrencyAddr)
actual = new(big.Int).Sub(funds, actual)
expected = new(big.Int).SetUint64(block.GasUsed() * (block.Transactions()[0].GasTipCap().Uint64() + block.BaseFee().Uint64()))
if actual.Cmp(expected) != 0 {
t.Fatalf("sender balance incorrect: expected %d, got %d", expected, actual)
}

// 5; Check that base fee has been moved to fee handler.
actual, _ = fee_currencies.GetBalanceOf(&backend, contracts.FeeHandlerAddress, FeeCurrencyAddr)
expected = new(big.Int).SetUint64(block.GasUsed() * block.BaseFee().Uint64())
if actual.Cmp(expected) != 0 {
t.Fatalf("fee handler balance incorrect: expected %d, got %d", expected, actual)
}
}
Loading

0 comments on commit 16fe6b3

Please sign in to comment.