Skip to content

Commit

Permalink
feat(gateway): improve Gateway contract (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
swift1337 authored Oct 10, 2024
1 parent 8f3a373 commit 5f108f9
Show file tree
Hide file tree
Showing 8 changed files with 358 additions and 272 deletions.
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @lumtis @fbac @swift1337 @skosito
78 changes: 74 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,80 @@ The project is built using [Blueprint](https://github.com/ton-org/blueprint).

## How to use

- Contract tests: `make test`
- Contract scripts: `make run`
- Contract compilation: `make compile`
- Compile FunC: `make compile`
- Run tests: `make test`
- Run Blueprint [scripts](https://github.com/ton-org/blueprint?tab=readme-ov-file#custom-scripts): `make run`

## How it works

`TBD`
### Deposits

All deposits are represented as internal messages that have the following structure:

- uint32 `op_code` - operation code. Standard for TON
- uint64 `query_id` - not used right now. Standard for TON
- ... the rest of the message is the operation-specific data

#### `deposit` (op 101)

```
op_code:uint32 query_id:uint64 evm_recipient:slice (160 bits)
```

Deposits funds to the contract (subtracting a small deposit fee to cover the gas costs).
ZetaChain will observe this tx and execute cross-chain deposit to `evm_recipient` on Zeta.

#### `deposit_and_call` (op 102)

```
op_code:uint32 query_id:uint64 evm_recipient:slice (160 bits) call_data:cell
```

Deposits funds to the contract (subtracting a small deposit fee to cover the gas costs).
ZetaChain will observe this tx and execute cross-chain deposit to `evm_recipient` on Zeta
AND call the contract with `call_data`.

Note that `call_data` should be
encoded as [snakeCell](https://docs.ton.org/develop/dapps/asset-processing/metadata#snake-data-encoding)

#### Authority operations

These "admin" operations are used to manage the contract. In the future, they will be fully managed by TSS.
Currently, a dedicated authority address is used `state::authority_address`

- `set_deposits_enabled` - toggle deposits
- `update_tss` - update TSS public key
- `update_code` - upgrade the contract code
- `update_authority` - update authority TON address

### Withdrawals

ZetaChain uses MPC (Multi Party Computation) to sign all outbound transactions using TSS (Threshold Signature Scheme).
Due to the technical implementation TSS uses ECDSA cryptography in opposite to EdDSA in TON. Thus, we need to
check ECDSA signatures in the contract on-chain.

All TSS commands are represented as external messages that have the following structure:

- `uint32 op_code` - operation code. Standard for TON
- `[65]byte signature` - ECDSA signature of the message hash (v, r, s)
- `[32]byte hash` - hash of the payload
- `ref cell payload` - the actual payload

By having this structure we can sign arbitrary messages using ECDSA, recover signature,
then ensure sender and proceed with the operation.

The payload for `op withdrawal (200)` is the following:

```
recipient:MsgAddr amount:Coins seqno:uint32
```

#### External message signature flow:

Let’s simplify the input as `["signature", "payload_hash", "payload_data"]`:

- With `signature + payload_hash`, we can derive the signer's public key -> check that the message comes from TSS.
- By having `payload_hash + payload_data`, we can check that the payload is **exactly**
the same as the one that was signed.
- Otherwise, the sender could take any valid `signature + payload_hash`,
append an **arbitrary payload**, and execute the contract on behalf of TSS (e.g. "withdraw 1000 TON to address X").
3 changes: 3 additions & 0 deletions contracts/common/errors.fc
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ const error::invalid_seqno = 109;

;; Deposits are disabled
const error::deposits_disabled = 110;

;; Authority sender is invalid
const error::invalid_authority = 111;
9 changes: 7 additions & 2 deletions contracts/common/state.fc
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ global int state::fees;
;; nonce
global int state::seqno;

;; TSS address as 20 bytes (160 bits)
;; TSS EVM address as 20 bytes (160 bits)
global slice state::tss_address;

() load_state() impure inline_ref {
;; Authority address on TON (tl-b MsgAddress)
global slice state::authority_address;

() load_state() impure inline {
var cs = get_data().begin_parse();

state::deposits_enabled = cs~load_uint(size::deposits_enabled);
Expand All @@ -29,6 +32,7 @@ global slice state::tss_address;

state::seqno = cs~load_uint(size::seqno);
state::tss_address = cs~load_bits(size::evm_address);
state::authority_address = cs~load_msg_addr();
}

() mutate_state() impure inline_ref {
Expand All @@ -38,6 +42,7 @@ global slice state::tss_address;
.store_coins(state::fees)
.store_uint(state::seqno, size::seqno)
.store_slice(state::tss_address)
.store_slice(state::authority_address)
.end_cell();

set_data(store);
Expand Down
Loading

0 comments on commit 5f108f9

Please sign in to comment.