Actions

Actions

Description

wrap

mint to address with oracle approvals

unwrap

burn (called by user)

regoracle

register oracle

unregoracle

unregister oracle

regcust

register custodian

unregcust

unregister custodian

pause

pause wrap, unwrap or any built-in erc20 functions

unpause

unpause wrap, unwrap or any build-in erc20 functions

getOracle

Get oracle status by ethereum address

getCustodian

Get custodian status by ethereum address

getApproval

getApproval status by obtid

  • If fewer than 3 oracles have approved a wrap, getApproval returns:

    • Number of approvals

    • Ethereum address where the wfio will be sent to

    • Amount

Result {
  '0': '1',
  '1': '0x009310e41f4746AFeca3Ac713e070598067A32db',
  '2': '30000000000'
}
  • Once 3 oracles have been approved, the approval is removed from the vector so returns zeros:

Result {
  '0': '0',
  '1': '0x0000000000000000000000000000000000000000',
  '2': '0'
}

State Variables

State variables

Description

custodian_count

Keeps track of the number of custodians active in the oracle. Required for consensus math

oracle_count

Keeps track of the number of custodians active in the oracle. Required for consensus math

uoracmapv

Incrementer used to generate unique id for unregoracle approval mapping

roracmapv

Incrementer used to generate unique id for regoracle approval mapping

ucustmapv

Incrementer used to generate unique id for unregcust approval mapping

rcustmapv

Incrementer used to generate unique id for regcust approval mapping

upausmapv

Incrementer used to generate unique id for unpause approval mapping

pausemapv

Incrementer used to generate unique id for pause approval mapping

owner

Used to store contract owner (msg.sender) when deployed

oraclelist

A list of oracle addresses

Events

Events

Description

wrapped

Event emitted when wrap has completed.
emit wrapped(account, amount, obtid);

unwrapped

Event emitted when user has unwrapped tokens.
emit unwrapped(fioaddress, amount);

custodian_registered

Event emitted when a custodian has been registered
event custodian_registered(address account, uint256 eid);

custodian_unregistered

Event emitted when a custodian has been unregistered
event custodian_unregistered(address account, uint256 eid);

oracle_registered

Event emitted when an oracle has been registered
event oracle_registered(address account, uint256 eid);

oracle_unregistered

Event emitted when an oracle has been unregistered
event oracle_unregistered(address account, uint256 eid);

Paused

Event emitted when the contract has been paused by custodians

Unpaused

Event emitted when the contract has been unpaused by custodians

Mappings

Mappings

Members

Description

Custodians
mapping (address=>custodian) custodians

custodian
- active

Keeps track of the custodians that registered another custodian and their activation

Oracles
mapping (address=>oracles) oracles

oracle
- active

Keeps track of the custodians that registered an oracle and the oracles activation count

Approvals
mapping (bytes => bool) approver;

pending
- approved
- account
- approvers

Keeps track of the approvals by obtid, the number of approvals, and the details of the approval
This table is also used for tracking pause/unpause, oracle and custodian registration approvals, the account and approvers state variables remain

Modifiers

Modifiers (Perms)

Action

Description

onlyOracle

wrapunwrap

Only wFIO oracle may use this function

onlyCustodian

regoracle
unregoracle
regcust
unregcust

Only wFIO custodian may use this function

whenPaused

unpause

Built into erc20 pausable security contract. Keeps an action from being called when paused

whenNotPaused

pause
wrap
unwrap

Built into erc20 pausable security contract. Keeps an action from being called when unpaused

Misc. Requirements

Issue

Summary

Decision

Max supply

Should we put in a max supply to prevent over-minting of wFIO? This would track the maximum number of wFIO that could be in circulation.

Not needed

Reason: if the ERC20 contract gets taken over an additional wFIO is minted, the most likely course of action will be to fork the contract and invalidate the bad transactions.

Max transaction size

Should we put a max transaction size limit on mint into the ERC20 contract.

Not needed

ERC20 contract key

What is the status of the key used to set the contract?

Key should only be used for spinning up the contract and should be burned.

“Pause” function for Custodians

What is the process for locking the wFIO contract if it gets compromised?

Adam: contract is pausable. Tracked in:

Oracle “Admin” functions

Do we need to enable the ability for Oracles to call various contract actions such as approve, transfer, mint, etc.

This can be performed in a couple of ways:
1 - The Oracles vote in who can execute the next essential action as follows:
Oracle 1 executes approval action (not to be confused with erc20 approve) to mint using FIO obtid xxxxxxxx
Oracle 2 executes approval action to transfer for the same FIO obtid to Alice

Oracle 3 executes approval action for transfer, but wrong recipient is provided. Trx goes to Alice defined by oracle 1 and 2

2 - The Oracles can sign the next transfer action as a multisig
This could be quite costly on the ethereum chain, but is possible to implement.
Example of multisig on ethereum https://github.com/christianlundkvist/simple-multisig/blob/master/contracts/SimpleMultiSig.sol

Pawel will create an Oracle/Custodian Wrapping Manual that includes use cases for how to respond to errors with wrap and unwrap.

Tracked in:

Custodian “Admin” functions

Are there contract actions that should be exposed to Custodian “admin” approval?

  • Pause switch is an admin function.

  • Use case: refunds. If someone calls unwrap to the wrong address and it gets lost. We may want to enable the ability for Custodians to call 2/3+1 approval for a “mint” refund.

    • This can already be done by the Oracles calling wrap to a specific Ethereum address.

Todo: Pawel will create an Oracle/Custodian Wrapping Manual that includes use cases for how to respond to errors with wrap and unwrap.

Tracked in:

Unwrap fee

Is there a fee for unwrap?

On unwrap, the user pays the gas fees.

ERC-20 contract key burn

Once we spin up the ERC-20 contract with multiple custodian keys, we will burn the contract key

Wrap/Unwrap

wrap

Create wFIO on Ethereum chain.

Registering oracles

Implementation

Request body

Parameter

Required

Format

Definition

account

Yes

string

Public address on ETH blockchain where wrapped FIO should be delivered.

amount

Yes

uint256

Amount of wFIO (in SUFs) to unwrap.

obtid

Yes

string

FIO chain transaction ID

Example

{
  "account": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B",
  "amount": 100000000000,
  "obtid": "dfe50aad8e2271f84f87b8e603776d7e7970c636bb899c8993c08e9e2d21c106"
}

Processing

Exception handling

Error condition

Trigger

Type

Error message

Invalid amount

Transfer amount is not valid.

400

"Invalid amount"

Invalid public address

Recipient public address is not valid

400

"Invalid public address"

No authority

The signer is not a registered Oracle and does not have authority to call this function

403

"Only a wFIO Oracle may call this function"

Contract paused

Contract is paused (built-in)

400

"Pausable: paused"

unwrap

Convert wFIO on Ethereum chain to FIO Tokens on FIO chain.

Implementation

Processing

Fees

Request body

Parameter

Required

Format

Definition

amount

Yes

uint256

Amount of wFIO (in SUFs) to unwrap.

fio_address

Yes

String

The FIO Address where FIO Tokens should be delivered.

Example

{
  "amount": 100000000000,
  "fio_address": "alice@wallet"
}

Processing

Exception handling

Error condition

Trigger

Type

Error message

Invalid FIO address

Recipient public address is not valid

400

"Invalid FIO address"

Invalid amount

Transfer amount is not valid.

400

"Invalid amount"

Insufficient balance

Balance is less than amount + oracle fee + chain fee

400

"Insufficient balance"

No authority

The signer is not a registered Oracle and does not have authority to call this function

403

"Only a wFIO Oracle may call this function"

Contract paused

Contract is paused (built-in)

400

"Pausable: paused"

Oracles - register/unregister

regoracle

Register Oracle.

Registering oracles

Implementation

Request body

Parameter

Required

Format

Definition

account

Yes

Ethereum public address

Ethereum address owned by the Oracle.

Example

{
  "account": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"
}

Processing

Exception handling

Error condition

Trigger

Type

Error message

Invalid address

Ethereum address is not valid

400

"Invalid address"

No authority

The signer is not a registered Custodian and does not have authority to call this function

403

"Only a wFIO custodian may call this function"

Already registered

The Ethereum address is already registered as an Oracle

400

“Oracle is already registered”

unregoracle

Unregister Oracle.

Implementation

Request body

Parameter

Required

Format

Definition

account

Yes

Ethereum public address

Ethereum address owned by the Oracle.

Example

{
  "account": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"
}

Processing

Exception handling

Error condition

Trigger

Type

Error message

Invalid oracle

Oracle is not registered

400

"Invalid oracle"

No authority

The signer is not a registered Custodian and does not have authority to call this function

403

"Only a wFIO custodian may call this function"

Custodians - register/unregister

regcust

Register Custodian

Registering Custodians

Implementation

Request body

Parameter

Required

Format

Definition

account

Yes

Ethereum public address

Ethereum address owned by the Custodian.

Example

{
  "account": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"
}

Processing

Exception handling

Error condition

Trigger

Type

fields:name

fields:value

Error message

Invalid address

Ethereum address is not valid

400

"account"

Value sent in, e.g. "invalid account"

"Invalid address"

No authority

The signer is not a registered Custodian and does not have authority to call this function

403

"Only a wFIO custodian may call this function"

Already registered

The Ethereum address is already registered as an Custodian

400

"account"

“Custodian is already registered”

unregcust

Unregister Custodian.

Implementation

Request body

Parameter

Required

Format

Definition

account

Yes

Ethereum public address

Ethereum address owned by the Custodian.

Example

{
  "account": "0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B"
}

Processing

Exception handling

Error condition

Trigger

Type

Error message

Invalid custodian

Custodian is not registered

400

"Invalid custodian"

Invalid address

Ethereum address is not valid

400

"Invalid address"

No authority

The signer is not a registered Custodian and does not have authority to call this function

403

"Only a wFIO custodian may call this function"

pause

Pause contract.

Implementation

Parameter

Required

Format

Definition

None

No

Processing

Exception handling

Error condition

Trigger

Type

Error message

Contract paused

Contract is already paused (built-in)

400

"Pausable: paused"

Already approved

Custodian already called pause

400

“msg.sender has already approved this pause”

unpause

Unpause contract.

Implementation

Parameter

Required

Format

Definition

None

No

Processing

Exception handling

Error condition

Trigger

Type

Error message

Contract unpaused

Contract is already unpaused (built-in)

400

"Pausable: unpaused"

Already approved

Custodian already called unpause

400

“msg.sender has already approved this unpause”

Ethereum json rpc error codes:

https://eth.wiki/json-rpc/json-rpc-error-codes-improvement-proposal

Example erc20 response body:

{
  tx: '0x3c9ffdcf06ac984b93f5c302cf63bdb33ddb9479eba34737dc1ff3cf819ef0a7',
  receipt: {
    transactionHash: '0x3c9ffdcf06ac984b93f5c302cf63bdb33ddb9479eba34737dc1ff3cf819ef0a7',
    transactionIndex: 0,
    blockHash: '0xc3503388ba0748373ab2596609b001391636a9a1d469fca73352a2f5709595af',
    blockNumber: 2,
    from: '0x996e32a723cfe4afcb30f5ee3db78808ee816114',
    to: '0x5f953f03c166d1609101ebfb7286b3526fea768b',
    gasUsed: 70446,
    cumulativeGasUsed: 70446,
    contractAddress: null,
    logs: [],
    status: true,
    logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
    rawLogs: []
  },
  logs: []
}