-
Notifications
You must be signed in to change notification settings - Fork 834
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore(bech32): Port bech32 extension (#2038)
* chore(bech32): Port bech32 precompile to Evmos repo * fix: add bech32 precompile init * run make format * fix: tests now use new testing setup * CHANGELOG * fix: update expected gas * fix: slim down testing suite --------- Co-authored-by: Vvaradinov <Vvaradinov@users.noreply.github.com> Co-authored-by: stepit <48993133+0xstepit@users.noreply.github.com>
- Loading branch information
1 parent
17c0a46
commit 2d66645
Showing
12 changed files
with
788 additions
and
2 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// SPDX-License-Identifier: LGPL-3.0-only | ||
pragma solidity >=0.8.17; | ||
|
||
/// @dev The Bech32I contract's address. | ||
address constant Bech32_PRECOMPILE_ADDRESS = 0x0000000000000000000000000000000000000400; | ||
|
||
/// @author Evmos Team | ||
/// @title Bech32 Precompiled Contract | ||
/// @dev The interface through which solidity contracts can convert addresses from | ||
/// hex to bech32 and vice versa. | ||
/// @custom:address 0x0000000000000000000000000000000000000400 | ||
interface Bech32I { | ||
/// @dev Defines a method for converting a hex formatted address to bech32. | ||
/// @param addr The hex address to be converted. | ||
/// @param prefix The human readable prefix (HRP) of the bech32 address. | ||
/// @return bech32Address The address in bech32 format. | ||
function hexToBech32( | ||
address addr, | ||
string memory prefix | ||
) external returns (string memory bech32Address); | ||
|
||
/// @dev Defines a method for converting a bech32 formatted address to hex. | ||
/// @param bech32Address The bech32 address to be converted. | ||
/// @return addr The address in hex format. | ||
function bech32ToHex( | ||
string memory bech32Address | ||
) external returns (address addr); | ||
} |
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,45 @@ | ||
[ | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "string", | ||
"name": "bech32Address", | ||
"type": "string" | ||
} | ||
], | ||
"name": "bech32ToHex", | ||
"outputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "addr", | ||
"type": "address" | ||
} | ||
], | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "addr", | ||
"type": "address" | ||
}, | ||
{ | ||
"internalType": "string", | ||
"name": "prefix", | ||
"type": "string" | ||
} | ||
], | ||
"name": "hexToBech32", | ||
"outputs": [ | ||
{ | ||
"internalType": "string", | ||
"name": "bech32Address", | ||
"type": "string" | ||
} | ||
], | ||
"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,91 @@ | ||
// Copyright Tharsis Labs Ltd.(Evmos) | ||
// SPDX-License-Identifier:ENCL-1.0(https://github.com/evmos/evmos/blob/main/LICENSE) | ||
|
||
package bech32 | ||
|
||
import ( | ||
"embed" | ||
"fmt" | ||
|
||
"github.com/ethereum/go-ethereum/accounts/abi" | ||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/vm" | ||
cmn "github.com/evmos/evmos/v15/precompiles/common" | ||
) | ||
|
||
var _ vm.PrecompiledContract = &Precompile{} | ||
|
||
const ( | ||
// PrecompileAddress defines the address of the bech32 precompile contract. | ||
PrecompileAddress = "0x0000000000000000000000000000000000000400" | ||
) | ||
|
||
// Embed abi json file to the executable binary. Needed when importing as dependency. | ||
// | ||
//go:embed abi.json | ||
var f embed.FS | ||
|
||
// Precompile defines the precompiled contract for Bech32 encoding. | ||
type Precompile struct { | ||
abi.ABI | ||
baseGas uint64 | ||
} | ||
|
||
// NewPrecompile creates a new bech32 Precompile instance as a | ||
// PrecompiledContract interface. | ||
func NewPrecompile(baseGas uint64) (*Precompile, error) { | ||
newABI, err := cmn.LoadABI(f, "abi.json") | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
if baseGas == 0 { | ||
return nil, fmt.Errorf("baseGas cannot be zero") | ||
} | ||
|
||
return &Precompile{ | ||
ABI: newABI, | ||
baseGas: baseGas, | ||
}, nil | ||
} | ||
|
||
// Address defines the address of the bech32 compile contract. | ||
// address: 0x0000000000000000000000000000000000000400 | ||
func (Precompile) Address() common.Address { | ||
return common.HexToAddress(PrecompileAddress) | ||
} | ||
|
||
// RequiredGas calculates the contract gas use. | ||
func (p Precompile) RequiredGas(_ []byte) uint64 { | ||
return p.baseGas | ||
} | ||
|
||
// Run executes the precompiled contract bech32 methods defined in the ABI. | ||
func (p Precompile) Run(_ *vm.EVM, contract *vm.Contract, _ bool) (bz []byte, err error) { | ||
methodID := contract.Input[:4] | ||
// NOTE: this function iterates over the method map and returns | ||
// the method with the given ID | ||
method, err := p.MethodById(methodID) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
argsBz := contract.Input[4:] | ||
args, err := method.Inputs.Unpack(argsBz) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
switch method.Name { | ||
case HexToBech32Method: | ||
bz, err = p.HexToBech32(method, args) | ||
case Bech32ToHexMethod: | ||
bz, err = p.Bech32ToHex(method, args) | ||
} | ||
|
||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return bz, nil | ||
} |
Oops, something went wrong.