Skip to content

Commit

Permalink
Pointers contracts: support for ERC1155 and CW1155 contracts (sei-pro…
Browse files Browse the repository at this point in the history
…tocol#1755)

* wip cw1155 pointer

* cleanup todos

* sync events with current standard

* fix query BalanceOfBatch

* fix import

* Fix up cwerc1155 compiled files

* Add 1155 requests into bindings

* queries

* follow same coding style

* Add cwerc1155.wasm binary to `/contracts`

* Add go code to support new pointer contract

* Fix typo

* Add updated protobuf files

* Fix up tests

* Deprecate pointer proposals

* queries

* follow same coding style

* safetransfer functions, royalyinfo, set approval

* adding in transfer and approval tests

* solc and abigen

* clean up unused artifacts

* Add all go bindings

* return unsupported for methods not supported in erc standard

* fix query BalanceOfBatch response

* Add new test files

* fix Erc1155BalanceOfBatchResponse

* More testing

* Update cwerc1155.wasm

* More tests

* return true/false instead of erroring in query IsApprovedForAll

* use correct response for query BalanceOfBatch

* pass optional token id field to evm query TotalSupply

* remove todos

* remove AllTokenInfo query

* Fix balances query struct

* Update and rebuild CW1155 pointer

* Add new cw1155 wasms

* merge

* Update cwerc1155.wasm

* Fix up ERC1155 pointer tests

* balanceOfBatch

* adding in expect calls

* remove unused import

* Round of updates to cw1155 contracts

* Update cw1155 pointer tests

* Fix: missing ERC1155TransferPayload

* removing unnecessary return

* Update binary

* Fix balance of batch

* add minor checks

* Update integration test with latest main updates

* Fix up erc721-payload and erc1155-payload cli commands

* Lint code

* Update integration test with new pointer contract code id

* Map CW1155 events to EVM

* updates from cw1155 base

* update cw1155 base

* Test events emissions for cw1155 events

* Update wasm build for cwerc1155

* Fix integration test 1

* update cw1155 cargo, add optimize script to cargo

* Update wasm builds

* Add migrations for 1155s

* Code quality

* Remove unnecessary lines

* updates from audit on cw1155 standard

* [P1-I-01] Validate parameters in the "balanceOfBatch" function

* build pointer wasm from audit changes

* update pointer wasms in other places

* [P1-H-01] Fix "safeBatchTransferFrom" - change to "onERC1155BatchReceived"

* [P1-I-02] Consider adding "ERC1155Burnable" to "CW1155ERC1155Pointer"

* Fix CW1155ERC1155Pointer.sol styles

* Update ERC1155 pointer artifacts

* send funds if empty msg in send and send_batch

* rebuild cw1155 pointer/standard

* fix version issue

* cw1155_base wasm fix

* Update and fix tests

* Fix tests

* Remove events from 1155 pointer so as not to double-emit

* Linting

---------

Co-authored-by: shab <[email protected]>
Co-authored-by: Mr Meat <[email protected]>
Co-authored-by: scottirvine <[email protected]>
  • Loading branch information
4 people authored Dec 5, 2024
1 parent 15333e5 commit 5ddb9ab
Show file tree
Hide file tree
Showing 82 changed files with 9,586 additions and 152 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ coverage.out
example/cosmwasm/echo/target
example/cosmwasm/cw20/target
example/cosmwasm/cw721/target
example/cosmwasm/cw1155/target

# Solidity contracts artifacts
contracts/artifacts
Expand Down
157 changes: 157 additions & 0 deletions app/receipt.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"math"
"math/big"
"strings"

wasmtypes "github.com/CosmWasm/wasmd/x/wasm/types"
sdk "github.com/cosmos/cosmos-sdk/types"
Expand All @@ -24,6 +25,10 @@ var ERC20TransferTopic = common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952
var ERC721TransferTopic = common.HexToHash("0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef")
var ERC721ApprovalTopic = common.HexToHash("0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925")
var ERC721ApproveAllTopic = common.HexToHash("0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31")
var ERC1155TransferSingleTopic = common.HexToHash("0xc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f62")
var ERC1155TransferBatchTopic = common.HexToHash("0x4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb")
var ERC1155ApprovalForAllTopic = common.HexToHash("0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31")
var ERC1155URITopic = common.HexToHash("0x6bb7ff708619ba0610cba295a58592e0451dee2622938c8755667688daf3529b")
var EmptyHash = common.HexToHash("0x0")
var TrueHash = common.HexToHash("0x1")

Expand Down Expand Up @@ -91,6 +96,16 @@ func (app *App) AddCosmosEventsToEVMReceiptIfApplicable(ctx sdk.Context, tx sdk.
}
continue
}
// check if there is a ERC1155 pointer to contract Addr
pointerAddr, _, exists = app.EvmKeeper.GetERC1155CW1155Pointer(ctx, contractAddr)
if exists {
log, eligible := app.translateCW1155Event(ctx, wasmEvent, pointerAddr, contractAddr)
if eligible {
log.Index = uint(len(logs))
logs = append(logs, log)
}
continue
}
}
if len(logs) == 0 {
return
Expand Down Expand Up @@ -319,6 +334,99 @@ func (app *App) translateCW721Event(ctx sdk.Context, wasmEvent abci.Event, point
return nil, false
}

func (app *App) translateCW1155Event(ctx sdk.Context, wasmEvent abci.Event, pointerAddr common.Address, contractAddr string) (*ethtypes.Log, bool) {
action, found := GetAttributeValue(wasmEvent, "action")
if !found {
return nil, false
}
var topics []common.Hash
switch action {
case "transfer_single", "mint_single", "burn_single":
fromHash := EmptyHash
toHash := EmptyHash
if action != "mint_single" {
fromHash = app.GetEvmAddressAttribute(ctx, wasmEvent, "owner")
}
if action != "burn_single" {
toHash = app.GetEvmAddressAttribute(ctx, wasmEvent, "recipient")
}
topics = []common.Hash{
ERC1155TransferSingleTopic,
app.GetEvmAddressAttribute(ctx, wasmEvent, "sender"),
fromHash,
toHash,
}
tokenID := GetTokenIDAttribute(wasmEvent)
if tokenID == nil {
return nil, false
}
tokenAmount, found := GetAmountAttribute(wasmEvent)
if !found {
return nil, false
}
dataHash1 := common.BigToHash(tokenID).Bytes()
dataHash2 := common.BigToHash(tokenAmount).Bytes()
return &ethtypes.Log{
Address: pointerAddr,
Topics: topics,
Data: append(dataHash1, dataHash2...),
}, true
case "transfer_batch", "mint_batch", "burn_batch":
fromHash := EmptyHash
toHash := EmptyHash
if action != "mint_batch" {
fromHash = app.GetEvmAddressAttribute(ctx, wasmEvent, "owner")
}
if action != "burn_batch" {
toHash = app.GetEvmAddressAttribute(ctx, wasmEvent, "recipient")
}
topics = []common.Hash{
ERC1155TransferBatchTopic,
app.GetEvmAddressAttribute(ctx, wasmEvent, "sender"),
fromHash,
toHash,
}
tokenIDs, found := GetTokenIDsAttribute(wasmEvent)
if !found {
return nil, false
}
tokenAmounts, found := GetAmountsAttribute(wasmEvent)
if !found {
return nil, false
}
value := EncodeBigIntArray(tokenIDs)
value = append(value, EncodeBigIntArray(tokenAmounts)...)
return &ethtypes.Log{
Address: pointerAddr,
Topics: topics,
Data: value,
}, true
case "approve_all":
topics = []common.Hash{
ERC1155ApprovalForAllTopic,
app.GetEvmAddressAttribute(ctx, wasmEvent, "sender"),
app.GetEvmAddressAttribute(ctx, wasmEvent, "operator"),
}
return &ethtypes.Log{
Address: pointerAddr,
Topics: topics,
Data: TrueHash.Bytes(),
}, true
case "revoke_all":
topics = []common.Hash{
ERC1155ApprovalForAllTopic,
app.GetEvmAddressAttribute(ctx, wasmEvent, "sender"),
app.GetEvmAddressAttribute(ctx, wasmEvent, "operator"),
}
return &ethtypes.Log{
Address: pointerAddr,
Topics: topics,
Data: EmptyHash.Bytes(),
}, true
}
return nil, false
}

func (app *App) GetEvmAddressAttribute(ctx sdk.Context, event abci.Event, attribute string) common.Hash {
addrStr, found := GetAttributeValue(event, attribute)
if found {
Expand Down Expand Up @@ -360,6 +468,22 @@ func GetAmountAttribute(event abci.Event) (*big.Int, bool) {
return nil, false
}

func GetAmountsAttribute(event abci.Event) ([]*big.Int, bool) {
results := []*big.Int{}
amounts, found := GetAttributeValue(event, "amounts")
if !found {
return results, false
}
for _, amt := range strings.Split(amounts, ",") {
amtInt, ok := sdk.NewIntFromString(amt)
if !ok {
return results, false
}
results = append(results, amtInt.BigInt())
}
return results, true
}

func GetTokenIDAttribute(event abci.Event) *big.Int {
tokenID, found := GetAttributeValue(event, "token_id")
if !found {
Expand All @@ -371,3 +495,36 @@ func GetTokenIDAttribute(event abci.Event) *big.Int {
}
return tokenIDInt.BigInt()
}

func GetTokenIDsAttribute(event abci.Event) ([]*big.Int, bool) {
results := []*big.Int{}
tokenIDs, found := GetAttributeValue(event, "token_ids")
if !found {
return results, false
}
for _, tid := range strings.Split(tokenIDs, ",") {
tidInt, ok := sdk.NewIntFromString(tid)
if !ok {
return results, false
}
results = append(results, tidInt.BigInt())
}
return results, true
}

func EncodeBigIntArray(inputs []*big.Int) []byte {
// Arrays are broken up into components:
// - offset byte (always 32)
// - length of array
// - ...array values
offset := big.NewInt(32)
length := big.NewInt(int64(len(inputs)))
value := append(
common.BigToHash(offset).Bytes(),
common.BigToHash(length).Bytes()...,
)
for _, i := range inputs {
value = append(value, common.BigToHash(i).Bytes()...)
}
return value
}
Loading

0 comments on commit 5ddb9ab

Please sign in to comment.