-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #157 from xpladev/feature/precompile
feat: precompile contracts
- Loading branch information
Showing
28 changed files
with
1,487 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"string","name":"denom","type":"string"}],"name":"balance","outputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"fromAddress","type":"address"},{"internalType":"address","name":"toAddress","type":"address"},{"internalType":"string","name":"denom","type":"string"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"send","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"denom","type":"string"}],"name":"supplyOf","outputs":[{"internalType":"uint256","name":"supply","type":"uint256"}],"stateMutability":"view","type":"function"}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
address constant BANK_PRECOMPILE_ADDRESS = 0x1000000000000000000000000000000000000001; | ||
|
||
IBank constant BANK_CONTRACT = IBank( | ||
BANK_PRECOMPILE_ADDRESS | ||
); | ||
|
||
interface IBank { | ||
// Transactions | ||
function send( | ||
address fromAddress, | ||
address toAddress, | ||
string calldata denom, | ||
uint256 amount | ||
) external returns (bool success); | ||
|
||
// Queries | ||
function balance( | ||
address addr, | ||
string memory denom | ||
) external view returns (uint256 balance); | ||
|
||
function supplyOf( | ||
string memory denom | ||
) external view returns (uint256 supply); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package bank | ||
|
||
import ( | ||
"embed" | ||
"errors" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/vm" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
|
||
"github.com/xpladev/ethermint/x/evm/statedb" | ||
|
||
"github.com/xpladev/xpla/precompile/util" | ||
) | ||
|
||
var _ vm.PrecompiledContract = PrecompiledBank{} | ||
|
||
var ( | ||
Address = common.HexToAddress(hexAddress) | ||
ABI = abi.ABI{} | ||
|
||
//go:embed IBank.abi | ||
abiFS embed.FS | ||
) | ||
|
||
type PrecompiledBank struct { | ||
bk BankKeeper | ||
} | ||
|
||
func init() { | ||
var err error | ||
ABI, err = util.LoadABI(abiFS, abiFile) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func NewPrecompiledBank(bk BankKeeper) PrecompiledBank { | ||
return PrecompiledBank{bk: bk} | ||
} | ||
|
||
func (p PrecompiledBank) RequiredGas(input []byte) uint64 { | ||
// Implement the method as needed | ||
return 0 | ||
} | ||
|
||
func (p PrecompiledBank) Run(evm *vm.EVM, input []byte) ([]byte, error) { | ||
method, argsBz := util.SplitInput(input) | ||
|
||
abiMethod, err := ABI.MethodById(method) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
args, err := abiMethod.Inputs.Unpack(argsBz) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ctx := evm.StateDB.(*statedb.StateDB).GetContext() | ||
|
||
switch MethodBank(abiMethod.Name) { | ||
case Balance: | ||
return p.balance(ctx, abiMethod, args) | ||
case Send: | ||
return p.send(ctx, evm.Origin, abiMethod, args) | ||
case Supply: | ||
return p.supplyOf(ctx, abiMethod, args) | ||
default: | ||
return nil, errors.New("method not found") | ||
} | ||
} | ||
|
||
func (p PrecompiledBank) balance(ctx sdk.Context, method *abi.Method, args []interface{}) ([]byte, error) { | ||
|
||
address, err := util.GetAccAddress(args[0]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
denom, err := util.GetString(args[1]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
coin := p.bk.GetBalance(ctx, address, denom) | ||
|
||
return method.Outputs.Pack(coin.Amount.BigInt()) | ||
} | ||
|
||
func (p PrecompiledBank) supplyOf(ctx sdk.Context, method *abi.Method, args []interface{}) ([]byte, error) { | ||
denom, err := util.GetString(args[0]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
coin := p.bk.GetSupply(ctx, denom) | ||
|
||
return method.Outputs.Pack(coin.Amount.BigInt()) | ||
} | ||
|
||
func (p PrecompiledBank) send(ctx sdk.Context, sender common.Address, method *abi.Method, args []interface{}) ([]byte, error) { | ||
|
||
fromAddress, err := util.GetAccAddress(args[0]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if err = util.ValidateSigner(fromAddress, sender); err != nil { | ||
return nil, err | ||
} | ||
|
||
toAddress, err := util.GetAccAddress(args[1]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
denom, err := util.GetString(args[2]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
amount, err := util.GetBigInt(args[3]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
err = p.bk.SendCoins(ctx, fromAddress, toAddress, sdk.NewCoins(sdk.NewCoin(denom, amount))) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return method.Outputs.Pack(true) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package bank | ||
|
||
const ( | ||
hexAddress = "0x1000000000000000000000000000000000000001" | ||
abiFile = "IBank.abi" | ||
) | ||
|
||
type MethodBank string | ||
|
||
const ( | ||
Balance MethodBank = "balance" | ||
Send MethodBank = "send" | ||
Supply MethodBank = "supplyOf" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package bank | ||
|
||
import ( | ||
"context" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
) | ||
|
||
type BankKeeper interface { | ||
GetBalance(context.Context, sdk.AccAddress, string) sdk.Coin | ||
GetSupply(context.Context, string) sdk.Coin | ||
SendCoins(context.Context, sdk.AccAddress, sdk.AccAddress, sdk.Coins) error | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
[{"inputs":[{"internalType":"address","name":"delegatorAddress","type":"address"},{"internalType":"address","name":"validatorAddress","type":"address"}],"name":"withdrawDelegatorReward","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.0; | ||
|
||
address constant DISTRIBUTION_PRECOMPILE_ADDRESS = 0x1000000000000000000000000000000000000003; | ||
|
||
IDistribution constant DISTRIBUTION_CONTRACT = IDistribution( | ||
DISTRIBUTION_PRECOMPILE_ADDRESS | ||
); | ||
|
||
interface IDistribution { | ||
// Transactions | ||
function withdrawDelegatorReward( | ||
address delegatorAddress, | ||
address validatorAddress | ||
) external returns (uint256 amount); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package distribution | ||
|
||
const ( | ||
hexAddress = "0x1000000000000000000000000000000000000003" | ||
abiFile = "IDistribution.abi" | ||
) | ||
|
||
type MethodDistribution string | ||
|
||
const ( | ||
WithdrawDelegatorReward MethodDistribution = "withdrawDelegatorReward" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
package distribution | ||
|
||
import ( | ||
"context" | ||
"embed" | ||
"errors" | ||
"math/big" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/vm" | ||
|
||
sdk "github.com/cosmos/cosmos-sdk/types" | ||
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" | ||
|
||
"github.com/xpladev/ethermint/x/evm/statedb" | ||
|
||
"github.com/xpladev/xpla/precompile/util" | ||
) | ||
|
||
var _ vm.PrecompiledContract = PrecompiledDistribution{} | ||
|
||
var ( | ||
Address = common.HexToAddress(hexAddress) | ||
ABI = abi.ABI{} | ||
|
||
//go:embed IDistribution.abi | ||
abiFS embed.FS | ||
) | ||
|
||
type PrecompiledDistribution struct { | ||
dk DistributionKeeper | ||
} | ||
|
||
func init() { | ||
var err error | ||
ABI, err = util.LoadABI(abiFS, abiFile) | ||
if err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func NewPrecompiledDistribution(dk DistributionKeeper) PrecompiledDistribution { | ||
return PrecompiledDistribution{dk: dk} | ||
} | ||
|
||
func (p PrecompiledDistribution) RequiredGas(input []byte) uint64 { | ||
// Implement the method as needed | ||
return 0 | ||
} | ||
|
||
func (p PrecompiledDistribution) Run(evm *vm.EVM, input []byte) ([]byte, error) { | ||
method, argsBz := util.SplitInput(input) | ||
|
||
abiMethod, err := ABI.MethodById(method) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
args, err := abiMethod.Inputs.Unpack(argsBz) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
ctx := evm.StateDB.(*statedb.StateDB).GetContext() | ||
|
||
switch MethodDistribution(abiMethod.Name) { | ||
case WithdrawDelegatorReward: | ||
return p.withdrawDelegatorReward(ctx, evm.Origin, abiMethod, args) | ||
default: | ||
return nil, errors.New("method not found") | ||
} | ||
} | ||
|
||
func (p PrecompiledDistribution) withdrawDelegatorReward(ctx context.Context, sender common.Address, method *abi.Method, args []interface{}) ([]byte, error) { | ||
delegatorAddress, err := util.GetAccAddress(args[0]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if err = util.ValidateSigner(delegatorAddress, sender); err != nil { | ||
return nil, err | ||
} | ||
|
||
validatorAddress, err := util.GetAccAddress(args[1]) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
msg := distributiontypes.NewMsgWithdrawDelegatorReward(delegatorAddress.String(), sdk.ValAddress(validatorAddress.Bytes()).String()) | ||
|
||
res, err := p.dk.WithdrawDelegatorReward(ctx, msg) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
amount := big.NewInt(0) | ||
if !res.Amount.IsZero() { | ||
amount = res.Amount[0].Amount.BigInt() | ||
} | ||
|
||
return method.Outputs.Pack(amount) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package distribution | ||
|
||
import ( | ||
"context" | ||
|
||
distributiontypes "github.com/cosmos/cosmos-sdk/x/distribution/types" | ||
) | ||
|
||
type DistributionKeeper interface { | ||
WithdrawDelegatorReward(ctx context.Context, msg *distributiontypes.MsgWithdrawDelegatorReward) (*distributiontypes.MsgWithdrawDelegatorRewardResponse, error) | ||
} |
Oops, something went wrong.