From 368844ad2a28ec07848e3c0169cf2b83b579a2e8 Mon Sep 17 00:00:00 2001
From: Aaron Buchwald <aaron.buchwald56@gmail.com>
Date: Mon, 23 Nov 2020 20:46:35 -0500
Subject: Add native asset precompiled contracts for apricot release

---
 plugin/evm/export_tx.go | 3 ++-
 plugin/evm/import_tx.go | 3 ++-
 plugin/evm/vm.go        | 9 +++++++++
 3 files changed, 13 insertions(+), 2 deletions(-)

(limited to 'plugin')

diff --git a/plugin/evm/export_tx.go b/plugin/evm/export_tx.go
index 2735573..2ebfeff 100644
--- a/plugin/evm/export_tx.go
+++ b/plugin/evm/export_tx.go
@@ -240,8 +240,8 @@ func (vm *VM) newExportTx(
 func (tx *UnsignedExportTx) EVMStateTransfer(vm *VM, state *state.StateDB) error {
 	addrs := map[[20]byte]uint64{}
 	for _, from := range tx.Ins {
-		log.Info("crosschain C->X", "addr", from.Address, "amount", from.Amount)
 		if from.AssetID == vm.ctx.AVAXAssetID {
+			log.Info("crosschain C->X", "from", from.Address, "amount", from.Amount, "assetID", "AVAX")
 			amount := new(big.Int).Mul(
 				new(big.Int).SetUint64(from.Amount), x2cRate)
 			if state.GetBalance(from.Address).Cmp(amount) < 0 {
@@ -250,6 +250,7 @@ func (tx *UnsignedExportTx) EVMStateTransfer(vm *VM, state *state.StateDB) error
 			state.SubBalance(from.Address, amount)
 		} else {
 			amount := new(big.Int).SetUint64(from.Amount)
+			log.Info("crosschain C->X", "from", from.Address, "amount", from.Amount, "assetID", from.AssetID)
 			if state.GetBalanceMultiCoin(from.Address, common.Hash(from.AssetID)).Cmp(amount) < 0 {
 				return errInsufficientFunds
 			}
diff --git a/plugin/evm/import_tx.go b/plugin/evm/import_tx.go
index 1ec394c..d6b4b7d 100644
--- a/plugin/evm/import_tx.go
+++ b/plugin/evm/import_tx.go
@@ -270,12 +270,13 @@ func (vm *VM) newImportTx(
 // accounts accordingly with the imported EVMOutputs
 func (tx *UnsignedImportTx) EVMStateTransfer(vm *VM, state *state.StateDB) error {
 	for _, to := range tx.Outs {
-		log.Info("crosschain X->C", "addr", to.Address, "amount", to.Amount)
 		if to.AssetID == vm.ctx.AVAXAssetID {
+			log.Info("crosschain X->C", "to", to.Address, "amount", to.Amount, "assetID", "AVAX")
 			amount := new(big.Int).Mul(
 				new(big.Int).SetUint64(to.Amount), x2cRate)
 			state.AddBalance(to.Address, amount)
 		} else {
+			log.Info("crosschain X->C", "to", to.Address, "amount", to.Amount, "assetID", to.AssetID)
 			amount := new(big.Int).SetUint64(to.Amount)
 			state.AddBalanceMultiCoin(to.Address, common.Hash(to.AssetID), amount)
 		}
diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go
index c9bdad9..fc571b9 100644
--- a/plugin/evm/vm.go
+++ b/plugin/evm/vm.go
@@ -239,6 +239,15 @@ func (vm *VM) Initialize(
 		return err
 	}
 
+	// Set the Apricot Fork Block on the ChainConfig
+	// TODO switch to correct block number of the fork
+	switch {
+	case g.Config.ChainID.Cmp(params.AvalancheMainnetChainID) == 0:
+		g.Config.ApricotBlock = nil
+	case g.Config.ChainID.Cmp(params.AvalancheFujiChainID) == 0:
+		g.Config.ApricotBlock = nil
+	}
+
 	vm.acceptedDB = prefixdb.New([]byte(acceptedPrefix), db)
 
 	vm.chainID = g.Config.ChainID
-- 
cgit v1.2.3-70-g09d2


From cc2a13f91f95bd377f5c3efb86ebbcc7096f6d97 Mon Sep 17 00:00:00 2001
From: Aaron Buchwald <aaron.buchwald56@gmail.com>
Date: Tue, 15 Dec 2020 17:30:03 -0500
Subject: Set chain rules based on block times for mainnet/fuji

---
 contracts/arc20.sol |  2 +-
 core/vm/evm.go      |  2 +-
 params/config.go    | 84 +++++++++++++++++++++++++++++++----------------------
 plugin/evm/vm.go    |  5 ++--
 4 files changed, 53 insertions(+), 40 deletions(-)

(limited to 'plugin')

diff --git a/contracts/arc20.sol b/contracts/arc20.sol
index a7fc997..d1af6a3 100644
--- a/contracts/arc20.sol
+++ b/contracts/arc20.sol
@@ -2,7 +2,7 @@
 
 pragma solidity >=0.6.0 <0.8.0;
 
-import {NativeAssets} from "./NativeAssets.sol";
+import {NativeAssets} from "./nativeAssets.sol";
 
 contract ARC20 {
 
diff --git a/core/vm/evm.go b/core/vm/evm.go
index ab04790..fe840da 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -152,7 +152,7 @@ func NewEVM(ctx Context, statedb StateDB, chainConfig *params.ChainConfig, vmCon
 		StateDB:      statedb,
 		vmConfig:     vmConfig,
 		chainConfig:  chainConfig,
-		chainRules:   chainConfig.Rules(ctx.BlockNumber),
+		chainRules:   chainConfig.AvalancheRules(ctx.BlockNumber, ctx.Time),
 		interpreters: make([]Interpreter, 0, 1),
 	}
 
diff --git a/params/config.go b/params/config.go
index 1e14c40..d5db94f 100644
--- a/params/config.go
+++ b/params/config.go
@@ -20,6 +20,7 @@ import (
 	"encoding/binary"
 	"fmt"
 	"math/big"
+	"time"
 
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/crypto"
@@ -62,40 +63,38 @@ var (
 var (
 	// AvalancheApricotMainnetChainConfig is the configuration for Avalanche Main Network
 	AvalancheApricotMainnetChainConfig = &ChainConfig{
-		ChainID:             AvalancheMainnetChainID,
-		HomesteadBlock:      big.NewInt(0),
-		DAOForkBlock:        big.NewInt(0),
-		DAOForkSupport:      true,
-		EIP150Block:         big.NewInt(0),
-		EIP150Hash:          common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
-		EIP155Block:         big.NewInt(0),
-		ByzantiumBlock:      big.NewInt(0),
-		ConstantinopleBlock: big.NewInt(0),
-		PetersburgBlock:     big.NewInt(0),
-		IstanbulBlock:       big.NewInt(0),
-		MuirGlacierBlock:    big.NewInt(0),
-		ApricotBlock:        big.NewInt(0), // TODO specify correct block height
+		ChainID:               AvalancheMainnetChainID,
+		HomesteadBlock:        big.NewInt(0),
+		DAOForkBlock:          big.NewInt(0),
+		DAOForkSupport:        true,
+		EIP150Block:           big.NewInt(0),
+		EIP150Hash:            common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
+		EIP155Block:           big.NewInt(0),
+		ByzantiumBlock:        big.NewInt(0),
+		ConstantinopleBlock:   big.NewInt(0),
+		PetersburgBlock:       big.NewInt(0),
+		IstanbulBlock:         big.NewInt(0),
+		MuirGlacierBlock:      big.NewInt(0),
+		ApricotBlockTimestamp: new(big.Int).SetUint64(uint64(time.Date(2021, 1, 7, 5, 00, 0, 0, time.UTC).Unix())),
 	}
 
 	// AvalancheApricotFujiChainConfig is the configuration for the Fuji Test Network
 	AvalancheApricotFujiChainConfig = &ChainConfig{
-		ChainID:             AvalancheFujiChainID,
-		HomesteadBlock:      big.NewInt(0),
-		DAOForkBlock:        big.NewInt(0),
-		DAOForkSupport:      true,
-		EIP150Block:         big.NewInt(0),
-		EIP150Hash:          common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
-		EIP155Block:         big.NewInt(0),
-		ByzantiumBlock:      big.NewInt(0),
-		ConstantinopleBlock: big.NewInt(0),
-		PetersburgBlock:     big.NewInt(0),
-		IstanbulBlock:       big.NewInt(0),
-		MuirGlacierBlock:    big.NewInt(0),
-		ApricotBlock:        big.NewInt(0), // TODO specify correct block height
+		ChainID:               AvalancheFujiChainID,
+		HomesteadBlock:        big.NewInt(0),
+		DAOForkBlock:          big.NewInt(0),
+		DAOForkSupport:        true,
+		EIP150Block:           big.NewInt(0),
+		EIP150Hash:            common.HexToHash("0x2086799aeebeae135c246c65021c82b4e15a2c451340993aacfd2751886514f0"),
+		EIP155Block:           big.NewInt(0),
+		ByzantiumBlock:        big.NewInt(0),
+		ConstantinopleBlock:   big.NewInt(0),
+		PetersburgBlock:       big.NewInt(0),
+		IstanbulBlock:         big.NewInt(0),
+		MuirGlacierBlock:      big.NewInt(0),
+		ApricotBlockTimestamp: new(big.Int).SetUint64(uint64(time.Date(2020, 12, 23, 5, 00, 0, 0, time.UTC).Unix())),
 	}
 
-	// TODO update local network genesis to enable Apricot
-
 	// MainnetChainConfig is the chain parameters to run a node on the main network.
 	MainnetChainConfig = &ChainConfig{
 		ChainID:             big.NewInt(1),
@@ -366,7 +365,11 @@ type ChainConfig struct {
 	YoloV1Block *big.Int `json:"yoloV1Block,omitempty"` // YOLO v1: https://github.com/ethereum/EIPs/pull/2657 (Ephemeral testnet)
 	EWASMBlock  *big.Int `json:"ewasmBlock,omitempty"`  // EWASM switch block (nil = no fork, 0 = already activated)
 
-	ApricotBlock *big.Int `json:"apricotBlock,omitempty"` // Apricot switch block (nil = no fork, 0 = already activated)
+	// Avalanche Network Upgrade Block Timestamps:
+
+	// Apricot switch block timestamp (nil = no fork, 0 = already activated)
+	// Apricot rules go into effect for blocks with a timestamp >= ApricotBlockTimestamp
+	ApricotBlockTimestamp *big.Int `json:"apricotBlock,omitempty"`
 
 	// Various consensus engines
 	Ethash *EthashConfig `json:"ethash,omitempty"`
@@ -403,7 +406,7 @@ func (c *ChainConfig) String() string {
 	default:
 		engine = "unknown"
 	}
-	return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, YOLO v1: %v, Apricot: %v, Engine: %v}",
+	return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, YOLO v1: %v, ApricotTimestamp: %v, Engine: %v}",
 		c.ChainID,
 		c.HomesteadBlock,
 		c.DAOForkBlock,
@@ -417,7 +420,7 @@ func (c *ChainConfig) String() string {
 		c.IstanbulBlock,
 		c.MuirGlacierBlock,
 		c.YoloV1Block,
-		c.ApricotBlock,
+		c.ApricotBlockTimestamp,
 		engine,
 	)
 }
@@ -484,9 +487,12 @@ func (c *ChainConfig) IsEWASM(num *big.Int) bool {
 	return isForked(c.EWASMBlock, num)
 }
 
-// IsApricot returns whether num represents a block number after the Apricot fork
-func (c *ChainConfig) IsApricot(num *big.Int) bool {
-	return isForked(c.ApricotBlock, num)
+// Avalanche Forks:
+
+// IsApricot returns whether num represents a block with a timestamp
+// after the Apricot fork time.
+func (c *ChainConfig) IsApricot(blockTimestamp *big.Int) bool {
+	return isForked(c.ApricotBlockTimestamp, blockTimestamp)
 }
 
 // TODO review how this works and see if it will work for a live transition
@@ -687,6 +693,14 @@ func (c *ChainConfig) Rules(num *big.Int) Rules {
 		IsPetersburg:     c.IsPetersburg(num),
 		IsIstanbul:       c.IsIstanbul(num),
 		IsYoloV1:         c.IsYoloV1(num),
-		IsApricot:        c.IsApricot(num),
 	}
 }
+
+// AvalancheRules returns the Avalanche modified rules to support Avalanche
+// network upgrades
+func (c *ChainConfig) AvalancheRules(blockNum, blockTimestamp *big.Int) Rules {
+	rules := c.Rules(blockNum)
+
+	rules.IsApricot = c.IsApricot(blockTimestamp)
+	return rules
+}
diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go
index fc571b9..2732a79 100644
--- a/plugin/evm/vm.go
+++ b/plugin/evm/vm.go
@@ -243,11 +243,10 @@ func (vm *VM) Initialize(
 	// TODO switch to correct block number of the fork
 	switch {
 	case g.Config.ChainID.Cmp(params.AvalancheMainnetChainID) == 0:
-		g.Config.ApricotBlock = nil
+		g.Config = params.AvalancheApricotMainnetChainConfig
 	case g.Config.ChainID.Cmp(params.AvalancheFujiChainID) == 0:
-		g.Config.ApricotBlock = nil
+		g.Config = params.AvalancheApricotFujiChainConfig
 	}
-
 	vm.acceptedDB = prefixdb.New([]byte(acceptedPrefix), db)
 
 	vm.chainID = g.Config.ChainID
-- 
cgit v1.2.3-70-g09d2


From faf845717a170e1c4baebaafef051d32058e2f99 Mon Sep 17 00:00:00 2001
From: Aaron Buchwald <aaron.buchwald56@gmail.com>
Date: Tue, 15 Dec 2020 17:34:48 -0500
Subject: Move params for network upgrade

---
 params/config.go | 11 +++++++++--
 plugin/evm/vm.go |  8 ++++----
 2 files changed, 13 insertions(+), 6 deletions(-)

(limited to 'plugin')

diff --git a/params/config.go b/params/config.go
index d5db94f..a0b4a51 100644
--- a/params/config.go
+++ b/params/config.go
@@ -53,6 +53,7 @@ var CheckpointOracles = map[common.Hash]*CheckpointOracleConfig{
 	GoerliGenesisHash:  GoerliCheckpointOracle,
 }
 
+// Avalanche ChainIDs
 var (
 	// AvalancheMainnetChainID ...
 	AvalancheMainnetChainID = big.NewInt(43114)
@@ -60,6 +61,12 @@ var (
 	AvalancheFujiChainID = big.NewInt(43113)
 )
 
+// Network upgrade block timestamps
+var (
+	AvalancheMainnetApricotTimestamp = new(big.Int).SetUint64(uint64(time.Date(2021, 1, 7, 5, 00, 0, 0, time.UTC).Unix()))
+	AvalancheFujiApricotTimestamp    = new(big.Int).SetUint64(uint64(time.Date(2020, 12, 23, 5, 00, 0, 0, time.UTC).Unix()))
+)
+
 var (
 	// AvalancheApricotMainnetChainConfig is the configuration for Avalanche Main Network
 	AvalancheApricotMainnetChainConfig = &ChainConfig{
@@ -75,7 +82,7 @@ var (
 		PetersburgBlock:       big.NewInt(0),
 		IstanbulBlock:         big.NewInt(0),
 		MuirGlacierBlock:      big.NewInt(0),
-		ApricotBlockTimestamp: new(big.Int).SetUint64(uint64(time.Date(2021, 1, 7, 5, 00, 0, 0, time.UTC).Unix())),
+		ApricotBlockTimestamp: AvalancheMainnetApricotTimestamp,
 	}
 
 	// AvalancheApricotFujiChainConfig is the configuration for the Fuji Test Network
@@ -92,7 +99,7 @@ var (
 		PetersburgBlock:       big.NewInt(0),
 		IstanbulBlock:         big.NewInt(0),
 		MuirGlacierBlock:      big.NewInt(0),
-		ApricotBlockTimestamp: new(big.Int).SetUint64(uint64(time.Date(2020, 12, 23, 5, 00, 0, 0, time.UTC).Unix())),
+		ApricotBlockTimestamp: AvalancheFujiApricotTimestamp,
 	}
 
 	// MainnetChainConfig is the chain parameters to run a node on the main network.
diff --git a/plugin/evm/vm.go b/plugin/evm/vm.go
index 2732a79..9f5607a 100644
--- a/plugin/evm/vm.go
+++ b/plugin/evm/vm.go
@@ -239,13 +239,13 @@ func (vm *VM) Initialize(
 		return err
 	}
 
-	// Set the Apricot Fork Block on the ChainConfig
-	// TODO switch to correct block number of the fork
+	// If Mainnet or Fuji ChainID is present then switch
+	// manually set the config
 	switch {
 	case g.Config.ChainID.Cmp(params.AvalancheMainnetChainID) == 0:
-		g.Config = params.AvalancheApricotMainnetChainConfig
+		g.Config.ApricotBlockTimestamp = params.AvalancheMainnetApricotTimestamp
 	case g.Config.ChainID.Cmp(params.AvalancheFujiChainID) == 0:
-		g.Config = params.AvalancheApricotFujiChainConfig
+		g.Config.ApricotBlockTimestamp = params.AvalancheFujiApricotTimestamp
 	}
 	vm.acceptedDB = prefixdb.New([]byte(acceptedPrefix), db)
 
-- 
cgit v1.2.3-70-g09d2