mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
Merge pull request #1 from limetester/lime_task_branch
Lime task branch
This commit is contained in:
commit
f34b4ccb28
19 changed files with 7217 additions and 43 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -14,6 +14,7 @@
|
|||
*/**/*tx_database*
|
||||
*/**/*dapps*
|
||||
build/_vendor/pkg
|
||||
.docker-compose.yml.swp
|
||||
|
||||
#*
|
||||
.#*
|
||||
|
|
|
|||
|
|
@ -171,5 +171,5 @@ i4O1UeWKs9owWttan9+PI47ozBSKOTxmMqLSQ0f56Np9FJsV0ilGxRKfjhzJ4KniOMUBA7mP
|
|||
epy6lH7HmxjjOR7eo0DaSxQGQpThAtFGwkWkFh8yki8j3E42kkrxvEyyYZDXn2YcI3bpqhJx
|
||||
PtwCMZUJ3kc/skOrs6bOI19iBNaEoNX5Dllm7UHjOgWNDQkcCuOCxucKano=
|
||||
=arte
|
||||
-----END PGP PUBLIC KEY BLOCK------
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ func TestWatchNewFile(t *testing.T) {
|
|||
func TestWatchNoDir(t *testing.T) {
|
||||
t.Parallel()
|
||||
// Create ks but not the directory that it watches.
|
||||
dir := filepath.Join(os.TempDir(), fmt.Sprintf("eth-keystore-watchnodir-test-%d-%d", os.Getpid(), rand.Int()))
|
||||
dir := filepath.Join(t.TempDir(), fmt.Sprintf("eth-keystore-watchnodir-test-%d-%d", os.Getpid(), rand.Int()))
|
||||
ks := NewKeyStore(dir, LightScryptN, LightScryptP)
|
||||
list := ks.Accounts()
|
||||
if len(list) > 0 {
|
||||
|
|
@ -126,7 +126,6 @@ func TestWatchNoDir(t *testing.T) {
|
|||
}
|
||||
// Create the directory and copy a key file into it.
|
||||
os.MkdirAll(dir, 0700)
|
||||
defer os.RemoveAll(dir)
|
||||
file := filepath.Join(dir, "aaa")
|
||||
if err := cp.CopyFile(file, cachetestAccounts[0].URL.Path); err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -27,9 +27,8 @@ import (
|
|||
// TestImportRaw tests clef --importraw
|
||||
func TestImportRaw(t *testing.T) {
|
||||
t.Parallel()
|
||||
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
||||
t.Cleanup(func() { os.Remove(keyPath) })
|
||||
|
||||
t.Run("happy-path", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
|
@ -68,9 +67,8 @@ func TestImportRaw(t *testing.T) {
|
|||
// TestListAccounts tests clef --list-accounts
|
||||
func TestListAccounts(t *testing.T) {
|
||||
t.Parallel()
|
||||
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
||||
t.Cleanup(func() { os.Remove(keyPath) })
|
||||
|
||||
t.Run("no-accounts", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
|
@ -97,9 +95,8 @@ func TestListAccounts(t *testing.T) {
|
|||
// TestListWallets tests clef --list-wallets
|
||||
func TestListWallets(t *testing.T) {
|
||||
t.Parallel()
|
||||
keyPath := filepath.Join(os.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||
keyPath := filepath.Join(t.TempDir(), fmt.Sprintf("%v-tempkey.test", t.Name()))
|
||||
os.WriteFile(keyPath, []byte("0102030405060708090a0102030405060708090a0102030405060708090a0102"), 0777)
|
||||
t.Cleanup(func() { os.Remove(keyPath) })
|
||||
|
||||
t.Run("no-accounts", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
|
|
|||
|
|
@ -34,12 +34,12 @@ import (
|
|||
"github.com/ethereum/go-ethereum/p2p"
|
||||
)
|
||||
|
||||
func makeJWTSecret() (string, [32]byte, error) {
|
||||
func makeJWTSecret(t *testing.T) (string, [32]byte, error) {
|
||||
var secret [32]byte
|
||||
if _, err := crand.Read(secret[:]); err != nil {
|
||||
return "", secret, fmt.Errorf("failed to create jwt secret: %v", err)
|
||||
}
|
||||
jwtPath := filepath.Join(os.TempDir(), "jwt_secret")
|
||||
jwtPath := filepath.Join(t.TempDir(), "jwt_secret")
|
||||
if err := os.WriteFile(jwtPath, []byte(hexutil.Encode(secret[:])), 0600); err != nil {
|
||||
return "", secret, fmt.Errorf("failed to prepare jwt secret file: %v", err)
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ func makeJWTSecret() (string, [32]byte, error) {
|
|||
}
|
||||
|
||||
func TestEthSuite(t *testing.T) {
|
||||
jwtPath, secret, err := makeJWTSecret()
|
||||
jwtPath, secret, err := makeJWTSecret(t)
|
||||
if err != nil {
|
||||
t.Fatalf("could not make jwt secret: %v", err)
|
||||
}
|
||||
|
|
@ -75,7 +75,7 @@ func TestEthSuite(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestSnapSuite(t *testing.T) {
|
||||
jwtPath, secret, err := makeJWTSecret()
|
||||
jwtPath, secret, err := makeJWTSecret(t)
|
||||
if err != nil {
|
||||
t.Fatalf("could not make jwt secret: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,7 @@ import (
|
|||
// TestExport does a basic test of "geth export", exporting the test-genesis.
|
||||
func TestExport(t *testing.T) {
|
||||
t.Parallel()
|
||||
outfile := fmt.Sprintf("%v/testExport.out", os.TempDir())
|
||||
defer os.Remove(outfile)
|
||||
outfile := fmt.Sprintf("%v/testExport.out", t.TempDir())
|
||||
geth := runGeth(t, "--datadir", initGeth(t), "export", outfile)
|
||||
geth.WaitExit()
|
||||
if have, want := geth.ExitStatus(), 0; have != want {
|
||||
|
|
|
|||
|
|
@ -201,9 +201,8 @@ func TestFileOut(t *testing.T) {
|
|||
var (
|
||||
have, want []byte
|
||||
err error
|
||||
path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63())
|
||||
path = fmt.Sprintf("%s/test_file_out-%d", t.TempDir(), rand.Int63())
|
||||
)
|
||||
t.Cleanup(func() { os.Remove(path) })
|
||||
if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "logtest"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -222,9 +221,8 @@ func TestRotatingFileOut(t *testing.T) {
|
|||
var (
|
||||
have, want []byte
|
||||
err error
|
||||
path = fmt.Sprintf("%s/test_file_out-%d", os.TempDir(), rand.Int63())
|
||||
path = fmt.Sprintf("%s/test_file_out-%d", t.TempDir(), rand.Int63())
|
||||
)
|
||||
t.Cleanup(func() { os.Remove(path) })
|
||||
if want, err = runSelf(fmt.Sprintf("--log.file=%s", path), "--log.rotate", "logtest"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,18 +29,12 @@ import (
|
|||
|
||||
// TestExport does basic sanity checks on the export/import functionality
|
||||
func TestExport(t *testing.T) {
|
||||
f := fmt.Sprintf("%v/tempdump", os.TempDir())
|
||||
defer func() {
|
||||
os.Remove(f)
|
||||
}()
|
||||
f := fmt.Sprintf("%v/tempdump", t.TempDir())
|
||||
testExport(t, f)
|
||||
}
|
||||
|
||||
func TestExportGzip(t *testing.T) {
|
||||
f := fmt.Sprintf("%v/tempdump.gz", os.TempDir())
|
||||
defer func() {
|
||||
os.Remove(f)
|
||||
}()
|
||||
f := fmt.Sprintf("%v/tempdump.gz", t.TempDir())
|
||||
testExport(t, f)
|
||||
}
|
||||
|
||||
|
|
@ -99,20 +93,14 @@ func testExport(t *testing.T, f string) {
|
|||
|
||||
// TestDeletionExport tests if the deletion markers can be exported/imported correctly
|
||||
func TestDeletionExport(t *testing.T) {
|
||||
f := fmt.Sprintf("%v/tempdump", os.TempDir())
|
||||
defer func() {
|
||||
os.Remove(f)
|
||||
}()
|
||||
f := fmt.Sprintf("%v/tempdump", t.TempDir())
|
||||
testDeletion(t, f)
|
||||
}
|
||||
|
||||
// TestDeletionExportGzip tests if the deletion markers can be exported/imported
|
||||
// correctly with gz compression.
|
||||
func TestDeletionExportGzip(t *testing.T) {
|
||||
f := fmt.Sprintf("%v/tempdump.gz", os.TempDir())
|
||||
defer func() {
|
||||
os.Remove(f)
|
||||
}()
|
||||
f := fmt.Sprintf("%v/tempdump.gz", t.TempDir())
|
||||
testDeletion(t, f)
|
||||
}
|
||||
|
||||
|
|
@ -171,10 +159,7 @@ func testDeletion(t *testing.T, f string) {
|
|||
// TestImportFutureFormat tests that we reject unsupported future versions.
|
||||
func TestImportFutureFormat(t *testing.T) {
|
||||
t.Parallel()
|
||||
f := fmt.Sprintf("%v/tempdump-future", os.TempDir())
|
||||
defer func() {
|
||||
os.Remove(f)
|
||||
}()
|
||||
f := fmt.Sprintf("%v/tempdump-future", t.TempDir())
|
||||
fh, err := os.OpenFile(f, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
|
|
|||
|
|
@ -22,10 +22,11 @@ import (
|
|||
)
|
||||
|
||||
func TestReadWriteFreezerTableMeta(t *testing.T) {
|
||||
f, err := os.CreateTemp(os.TempDir(), "*")
|
||||
f, err := os.CreateTemp(t.TempDir(), "*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create file %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
err = writeMetadata(f, newMetadata(100))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to write metadata %v", err)
|
||||
|
|
@ -43,10 +44,11 @@ func TestReadWriteFreezerTableMeta(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestInitializeFreezerTableMeta(t *testing.T) {
|
||||
f, err := os.CreateTemp(os.TempDir(), "*")
|
||||
f, err := os.CreateTemp(t.TempDir(), "*")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create file %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
meta, err := loadMetadata(f, uint64(100))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to read metadata %v", err)
|
||||
|
|
|
|||
|
|
@ -572,6 +572,6 @@ func deriveChainId(v *big.Int) *big.Int {
|
|||
}
|
||||
return new(big.Int).SetUint64((v - 35) / 2)
|
||||
}
|
||||
v.Sub(v, big.NewInt(35))
|
||||
return v.Rsh(v, 1)
|
||||
vCopy := new(big.Int).Sub(v, big.NewInt(35))
|
||||
return vCopy.Rsh(vCopy, 1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -345,6 +345,41 @@ func TestTransactionCoding(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestLegacyTransaction_ConsistentV_LargeChainIds(t *testing.T) {
|
||||
chainId := new(big.Int).SetUint64(13317435930671861669)
|
||||
|
||||
txdata := &LegacyTx{
|
||||
Nonce: 1,
|
||||
Gas: 1,
|
||||
GasPrice: big.NewInt(2),
|
||||
Data: []byte("abcdef"),
|
||||
}
|
||||
|
||||
key, err := crypto.GenerateKey()
|
||||
if err != nil {
|
||||
t.Fatalf("could not generate key: %v", err)
|
||||
}
|
||||
|
||||
tx, err := SignNewTx(key, NewEIP2930Signer(chainId), txdata)
|
||||
if err != nil {
|
||||
t.Fatalf("could not sign transaction: %v", err)
|
||||
}
|
||||
|
||||
// Make a copy of the initial V value
|
||||
preV, _, _ := tx.RawSignatureValues()
|
||||
preV = new(big.Int).Set(preV)
|
||||
|
||||
if tx.ChainId().Cmp(chainId) != 0 {
|
||||
t.Fatalf("wrong chain id: %v", tx.ChainId())
|
||||
}
|
||||
|
||||
v, _, _ := tx.RawSignatureValues()
|
||||
|
||||
if v.Cmp(preV) != 0 {
|
||||
t.Fatalf("wrong v value: %v", v)
|
||||
}
|
||||
}
|
||||
|
||||
func encodeDecodeJSON(tx *Transaction) (*Transaction, error) {
|
||||
data, err := json.Marshal(tx)
|
||||
if err != nil {
|
||||
|
|
|
|||
12
docker-compose/docker-compose.yml
Normal file
12
docker-compose/docker-compose.yml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
version: '3.8'
|
||||
|
||||
services:
|
||||
geth:
|
||||
image: denislav-mladenov/go-ethereum:latest
|
||||
ports:
|
||||
- "8545:8545"
|
||||
- "30303:30303"
|
||||
volumes:
|
||||
- ./data:/root/.ethereum
|
||||
command: --dev --http --http.addr 0.0.0.0 --http.port 8545 --http.api eth,net,web3,personal,miner
|
||||
|
||||
17
hardhat/.gitignore
vendored
Normal file
17
hardhat/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
node_modules
|
||||
.env
|
||||
|
||||
# Hardhat files
|
||||
/cache
|
||||
/artifacts
|
||||
|
||||
# TypeChain files
|
||||
/typechain
|
||||
/typechain-types
|
||||
|
||||
# solidity-coverage files
|
||||
/coverage
|
||||
/coverage.json
|
||||
|
||||
# Hardhat Ignition default folder for deployments against a local node
|
||||
ignition/deployments/chain-31337
|
||||
66
hardhat/contracts/Token.sol
Normal file
66
hardhat/contracts/Token.sol
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
//SPDX-License-Identifier: UNLICENSED
|
||||
|
||||
// Solidity files have to start with this pragma.
|
||||
// It will be used by the Solidity compiler to validate its version.
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
|
||||
// This is the main building block for smart contracts.
|
||||
contract Token {
|
||||
// Some string type variables to identify the token.
|
||||
string public name = "My Hardhat Token";
|
||||
string public symbol = "MHT";
|
||||
|
||||
// The fixed amount of tokens, stored in an unsigned integer type variable.
|
||||
uint256 public totalSupply = 1000000;
|
||||
|
||||
// An address type variable is used to store ethereum accounts.
|
||||
address public owner;
|
||||
|
||||
// A mapping is a key/value map. Here we store each account's balance.
|
||||
mapping(address => uint256) balances;
|
||||
|
||||
// The Transfer event helps off-chain applications understand
|
||||
// what happens within your contract.
|
||||
event Transfer(address indexed _from, address indexed _to, uint256 _value);
|
||||
|
||||
/**
|
||||
* Contract initialization.
|
||||
*/
|
||||
constructor() {
|
||||
// The totalSupply is assigned to the transaction sender, which is the
|
||||
// account that is deploying the contract.
|
||||
balances[msg.sender] = totalSupply;
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to transfer tokens.
|
||||
*
|
||||
* The `external` modifier makes a function *only* callable from *outside*
|
||||
* the contract.
|
||||
*/
|
||||
function transfer(address to, uint256 amount) external {
|
||||
// Check if the transaction sender has enough tokens.
|
||||
// If `require`'s first argument evaluates to `false`, the
|
||||
// transaction will revert.
|
||||
require(balances[msg.sender] >= amount, "Not enough tokens");
|
||||
|
||||
// Transfer the amount.
|
||||
balances[msg.sender] -= amount;
|
||||
balances[to] += amount;
|
||||
|
||||
// Notify off-chain applications of the transfer.
|
||||
emit Transfer(msg.sender, to, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read only function to retrieve the token balance of a given account.
|
||||
*
|
||||
* The `view` modifier indicates that it doesn't modify the contract's
|
||||
* state, which allows us to call it without executing a transaction.
|
||||
*/
|
||||
function balanceOf(address account) external view returns (uint256) {
|
||||
return balances[account];
|
||||
}
|
||||
}
|
||||
6
hardhat/hardhat.config.js
Normal file
6
hardhat/hardhat.config.js
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
require("@nomicfoundation/hardhat-toolbox");
|
||||
|
||||
/** @type import('hardhat/config').HardhatUserConfig */
|
||||
module.exports = {
|
||||
solidity: "0.8.24",
|
||||
};
|
||||
9
hardhat/ignition/modules/Token.js
Normal file
9
hardhat/ignition/modules/Token.js
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
const { buildModule } = require("@nomicfoundation/hardhat-ignition/modules");
|
||||
|
||||
const TokenModule = buildModule("TokenModule", (m) => {
|
||||
const token = m.contract("Token");
|
||||
|
||||
return { token };
|
||||
});
|
||||
|
||||
module.exports = TokenModule;
|
||||
6905
hardhat/package-lock.json
generated
Normal file
6905
hardhat/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
23
hardhat/package.json
Normal file
23
hardhat/package.json
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"name": "hardhat-pacage",
|
||||
"version": "1.0.0",
|
||||
"description": "denis hardhat project",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/denislav-mladenov/go-ethereum.git"
|
||||
},
|
||||
"author": "denis",
|
||||
"license": "ISC",
|
||||
"bugs": {
|
||||
"url": "https://github.com/denislav-mladenov/go-ethereum/issues"
|
||||
},
|
||||
"homepage": "https://github.com/denislav-mladenov/go-ethereum#readme",
|
||||
"devDependencies": {
|
||||
"@nomicfoundation/hardhat-toolbox": "^5.0.0",
|
||||
"hardhat": "^2.22.6"
|
||||
}
|
||||
}
|
||||
120
hardhat/test/Token.js
Normal file
120
hardhat/test/Token.js
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
// This is an example test file. Hardhat will run every *.js file in `test/`,
|
||||
// so feel free to add new ones.
|
||||
|
||||
// Hardhat tests are normally written with Mocha and Chai.
|
||||
|
||||
// We import Chai to use its asserting functions here.
|
||||
const { expect } = require("chai");
|
||||
|
||||
// We use `loadFixture` to share common setups (or fixtures) between tests.
|
||||
// Using this simplifies your tests and makes them run faster, by taking
|
||||
// advantage of Hardhat Network's snapshot functionality.
|
||||
const {
|
||||
loadFixture,
|
||||
} = require("@nomicfoundation/hardhat-toolbox/network-helpers");
|
||||
|
||||
// `describe` is a Mocha function that allows you to organize your tests.
|
||||
// Having your tests organized makes debugging them easier. All Mocha
|
||||
// functions are available in the global scope.
|
||||
//
|
||||
// `describe` receives the name of a section of your test suite, and a
|
||||
// callback. The callback must define the tests of that section. This callback
|
||||
// can't be an async function.
|
||||
describe("Token contract", function () {
|
||||
// We define a fixture to reuse the same setup in every test. We use
|
||||
// loadFixture to run this setup once, snapshot that state, and reset Hardhat
|
||||
// Network to that snapshot in every test.
|
||||
async function deployTokenFixture() {
|
||||
// Get the Signers here.
|
||||
const [owner, addr1, addr2] = await ethers.getSigners();
|
||||
|
||||
// To deploy our contract, we just have to call ethers.deployContract and await
|
||||
// its waitForDeployment() method, which happens once its transaction has been
|
||||
// mined.
|
||||
const hardhatToken = await ethers.deployContract("Token");
|
||||
|
||||
await hardhatToken.waitForDeployment();
|
||||
|
||||
// Fixtures can return anything you consider useful for your tests
|
||||
return { hardhatToken, owner, addr1, addr2 };
|
||||
}
|
||||
|
||||
// You can nest describe calls to create subsections.
|
||||
describe("Deployment", function () {
|
||||
// `it` is another Mocha function. This is the one you use to define each
|
||||
// of your tests. It receives the test name, and a callback function.
|
||||
//
|
||||
// If the callback function is async, Mocha will `await` it.
|
||||
it("Should set the right owner", async function () {
|
||||
// We use loadFixture to setup our environment, and then assert that
|
||||
// things went well
|
||||
const { hardhatToken, owner } = await loadFixture(deployTokenFixture);
|
||||
|
||||
// `expect` receives a value and wraps it in an assertion object. These
|
||||
// objects have a lot of utility methods to assert values.
|
||||
|
||||
// This test expects the owner variable stored in the contract to be
|
||||
// equal to our Signer's owner.
|
||||
expect(await hardhatToken.owner()).to.equal(owner.address);
|
||||
});
|
||||
|
||||
it("Should assign the total supply of tokens to the owner", async function () {
|
||||
const { hardhatToken, owner } = await loadFixture(deployTokenFixture);
|
||||
const ownerBalance = await hardhatToken.balanceOf(owner.address);
|
||||
expect(await hardhatToken.totalSupply()).to.equal(ownerBalance);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Transactions", function () {
|
||||
it("Should transfer tokens between accounts", async function () {
|
||||
const { hardhatToken, owner, addr1, addr2 } = await loadFixture(
|
||||
deployTokenFixture
|
||||
);
|
||||
// Transfer 50 tokens from owner to addr1
|
||||
await expect(
|
||||
hardhatToken.transfer(addr1.address, 50)
|
||||
).to.changeTokenBalances(hardhatToken, [owner, addr1], [-50, 50]);
|
||||
|
||||
// Transfer 50 tokens from addr1 to addr2
|
||||
// We use .connect(signer) to send a transaction from another account
|
||||
await expect(
|
||||
hardhatToken.connect(addr1).transfer(addr2.address, 50)
|
||||
).to.changeTokenBalances(hardhatToken, [addr1, addr2], [-50, 50]);
|
||||
});
|
||||
|
||||
it("Should emit Transfer events", async function () {
|
||||
const { hardhatToken, owner, addr1, addr2 } = await loadFixture(
|
||||
deployTokenFixture
|
||||
);
|
||||
|
||||
// Transfer 50 tokens from owner to addr1
|
||||
await expect(hardhatToken.transfer(addr1.address, 50))
|
||||
.to.emit(hardhatToken, "Transfer")
|
||||
.withArgs(owner.address, addr1.address, 50);
|
||||
|
||||
// Transfer 50 tokens from addr1 to addr2
|
||||
// We use .connect(signer) to send a transaction from another account
|
||||
await expect(hardhatToken.connect(addr1).transfer(addr2.address, 50))
|
||||
.to.emit(hardhatToken, "Transfer")
|
||||
.withArgs(addr1.address, addr2.address, 50);
|
||||
});
|
||||
|
||||
it("Should fail if sender doesn't have enough tokens", async function () {
|
||||
const { hardhatToken, owner, addr1 } = await loadFixture(
|
||||
deployTokenFixture
|
||||
);
|
||||
const initialOwnerBalance = await hardhatToken.balanceOf(owner.address);
|
||||
|
||||
// Try to send 1 token from addr1 (0 tokens) to owner.
|
||||
// `require` will evaluate false and revert the transaction.
|
||||
await expect(
|
||||
hardhatToken.connect(addr1).transfer(owner.address, 1)
|
||||
).to.be.revertedWith("Not enough tokens");
|
||||
|
||||
// Owner balance shouldn't have changed.
|
||||
expect(await hardhatToken.balanceOf(owner.address)).to.equal(
|
||||
initialOwnerBalance
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
Loading…
Reference in a new issue