From 8aaee4d700e15c257bf9c719bb3e8f323b5e0879 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Wed, 5 Dec 2018 15:28:15 +0100 Subject: [PATCH 1/8] draft: initial motivation --- OIPS/oip-draft_ux_composer.md | 110 ++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 OIPS/oip-draft_ux_composer.md diff --git a/OIPS/oip-draft_ux_composer.md b/OIPS/oip-draft_ux_composer.md new file mode 100644 index 0000000..d8dc31e --- /dev/null +++ b/OIPS/oip-draft_ux_composer.md @@ -0,0 +1,110 @@ +--- +oip: +title: +author: +discussions-to: +status: Draft +type: +created: <2018-11-28> +--- + +## Simple Summary + +The Branded Token contract for a token economy should be independent +of the layer-2 scaling technology used to run the application; +nor should the scaling contracts be specific to the Branded Token. +Enforcing a clean separation on the interfaces of these contracts, +in turn requires the user to sign more independent transactions. + +We propose a composition pattern to combine actions across different +contracts in to fewer combined actions (signatures) for the user through +the use of an optional UX Composer contract. Such a UX Composer contract +should be stateless and transparant such that only the users intended actions +can be executed. + +## Abstract + +A composition contract can be used to optimise the UX flow of +the user across multiple contracts whoes interfaces should not +tightly couple, but where the user intends to perform a single +combined action. + +## Motivation + +It is important that the user clearly understands the intended action +she signs a transaction for. However, for more advanced actions the single +intended action can involve multiple transactions. A composition contract can +facilitate the user experience for common interaction flows across multiple contracts. + +## Specification + + +For a first version, every staker deploys her own Gateway composer contract (UXC), +because the messagebus nonce in gateway locks a single message per staker - +and the UXC contract address is the `staker` for the gateway contract. +A UXC can be (re-)used for multiple gateways in parallel. + +Assumptions: +- staking OST originates from a hardware wallet + +```solidity +contract GatewayComposer { + + constructor ( + address _owner, + address _brandedToken) + + function requestStake( + /// amount in OST + uint256 _amount, + /// expected amount in BT + uint256 _expectedAmount, + /// intended gateway + address _gateway, + /// intended beneficiary address on the metablockchain + address _beneficiary, + /// gas price for facilitator fee in (U)BT + uint256 _gasPrice, + /// gas limit for message passing + uint256 _gasLimit, + /// messagebus nonce for staker + uint256 _nonce + ) + returns (uint256 stakedAmount_) + { + require(_expectedAmount == BT.convert(_amount)); + OST.transferFrom(msg.sender, this, _expectedAmount); + OST.approve(BT, _expectedAmount); + BT.requestStake(_amount, _expectedAmount); + + stakeRequests[gateway] = StakeRequest({ + expectedAmount: _expectedAmount, + // gateway: _gateway, + beneficiary: _beneficiary, + gasPrice: _gasPrice, + gasLimit: _gasLimit, + nonce: _nonce, + }); + } + + function acceptStakeRequest() +} +``` + + + +## Rationale + +The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.--> + +## Backwards Compatibility + +All OIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The OIP must explain how the author proposes to deal with these incompatibilities. OIP submissions without a sufficient backwards compatibility treatise may be rejected outright. + +## Test Cases + +Test cases for an implementation are mandatory for OIPs that are affecting consensus changes. Other OIPs can choose to include links to test cases if applicable. + +## Implementation + +The implementations must be completed before any OIP is given status "Final", but it need not be completed before the OIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details. From 1a6bf45b707439489b5ee5f26c0f1fb4285e9f61 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 17 Dec 2018 14:58:34 +0100 Subject: [PATCH 2/8] uxc: start specification --- OIPS/oip-draft_ux_composer.md | 107 ++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 37 deletions(-) diff --git a/OIPS/oip-draft_ux_composer.md b/OIPS/oip-draft_ux_composer.md index d8dc31e..59791f1 100644 --- a/OIPS/oip-draft_ux_composer.md +++ b/OIPS/oip-draft_ux_composer.md @@ -17,9 +17,9 @@ Enforcing a clean separation on the interfaces of these contracts, in turn requires the user to sign more independent transactions. We propose a composition pattern to combine actions across different -contracts in to fewer combined actions (signatures) for the user through -the use of an optional UX Composer contract. Such a UX Composer contract -should be stateless and transparant such that only the users intended actions +contracts into fewer combined actions (requiring less signatures) for the user +through the use of an optional UX Composer contract. Such a UX Composer +contract should be transparant such that only the users intended actions can be executed. ## Abstract @@ -33,52 +33,97 @@ combined action. It is important that the user clearly understands the intended action she signs a transaction for. However, for more advanced actions the single -intended action can involve multiple transactions. A composition contract can -facilitate the user experience for common interaction flows across multiple contracts. +intended action can involve multiple transactions to multiple contracts. +A composition contract can facilitate the user experience for common +interaction flows across multiple contracts. ## Specification -For a first version, every staker deploys her own Gateway composer contract (UXC), +We can think of the UX composer as a macro automating user actions. Users can +remove their macros and deploy improved ones. + +We detail a UX composer for a user who wants to stake OST +in a Branded Token (BT) contract and following that stake the Branded Tokens +into a gateway contract to mint the same amount as Utility Branded Tokens (UBT) +on the sidechain to use within the application of the token. + +Every staker deploys her own Gateway composer contract (UXC), because the messagebus nonce in gateway locks a single message per staker - and the UXC contract address is the `staker` for the gateway contract. A UXC can be (re-)used for multiple gateways in parallel. Assumptions: -- staking OST originates from a hardware wallet +- staking OST originates from a hardware wallet (currently no support for + EIP-721) + +Flow BrandedToken+Gateway: + +1. User approves transfer of OST to composer `OST.approve(uxc, amount)` (SIGN1) +2. User requests stake from composer `uxc.requestStake(...)` (SIGN2) + +```solidity +// see more detailed pseudocode below +function uxc:requestStake() +{ + // move OST from user to uxc + // uxc.requestStake(stakeVT, mintVBT); + // store struct with +} +``` + +## Rationale + +The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.--> + +## Backwards Compatibility + +All OIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The OIP must explain how the author proposes to deal with these incompatibilities. OIP submissions without a sufficient backwards compatibility treatise may be rejected outright. + +## Test Cases + +Test cases for an implementation are mandatory for OIPs that are affecting consensus changes. Other OIPs can choose to include links to test cases if applicable. + +## Implementation + +Sketch pieces of code to guide ```solidity contract GatewayComposer { constructor ( address _owner, - address _brandedToken) + eip20tokenI _ost, + ValueBackedI _brandedToken) function requestStake( - /// amount in OST - uint256 _amount, - /// expected amount in BT - uint256 _expectedAmount, - /// intended gateway + /// amount in VT (Value Token, set to OST) + uint256 _stakeVT, + /// expected amount in VBT + uint256 _mintVBT, + /// gateway to transfer VBT into address _gateway, - /// intended beneficiary address on the metablockchain + /// beneficiary address on the metablockchain address _beneficiary, /// gas price for facilitator fee in (U)BT uint256 _gasPrice, /// gas limit for message passing uint256 _gasLimit, /// messagebus nonce for staker + /// note: don't attempt to compute the nonce in UXC uint256 _nonce ) + onlyOwner returns (uint256 stakedAmount_) { - require(_expectedAmount == BT.convert(_amount)); - OST.transferFrom(msg.sender, this, _expectedAmount); - OST.approve(BT, _expectedAmount); - BT.requestStake(_amount, _expectedAmount); + require(_mintVBT == BT.convert(_stakeVT)); + require(OST.transferFrom(msg.sender, this, _stakeVT)); + OST.approve(VBT, _stakeVT); + require(VBT.requestStake(_stakeVT, _mintVBT)); stakeRequests[gateway] = StakeRequest({ - expectedAmount: _expectedAmount, + stakeVT: stakeVT, + mintVBT: _mintVBT, // gateway: _gateway, beneficiary: _beneficiary, gasPrice: _gasPrice, @@ -88,23 +133,11 @@ contract GatewayComposer { } function acceptStakeRequest() -} -``` - - - -## Rationale - -The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.--> -## Backwards Compatibility - -All OIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The OIP must explain how the author proposes to deal with these incompatibilities. OIP submissions without a sufficient backwards compatibility treatise may be rejected outright. - -## Test Cases - -Test cases for an implementation are mandatory for OIPs that are affecting consensus changes. Other OIPs can choose to include links to test cases if applicable. + function transferVT(...) onlyOwner + function approveVT(...) onlyOwner -## Implementation - -The implementations must be completed before any OIP is given status "Final", but it need not be completed before the OIP is accepted. While there is merit to the approach of reaching consensus on the specification and rationale before writing code, the principle of "rough consensus and running code" is still useful when it comes to resolving many discussions of API details. + function transferVBT(...) onlyOwner + function approveVBT(...) onlyOwner +} +``` \ No newline at end of file From c698415b37b29c6ad8d89d129c9a816443dd126a Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 17 Dec 2018 19:43:09 +0100 Subject: [PATCH 3/8] uxc: complete first draft of specification; up for discussion --- OIPS/oip-draft_ux_composer.md | 87 +++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 18 deletions(-) diff --git a/OIPS/oip-draft_ux_composer.md b/OIPS/oip-draft_ux_composer.md index 59791f1..43055c3 100644 --- a/OIPS/oip-draft_ux_composer.md +++ b/OIPS/oip-draft_ux_composer.md @@ -53,14 +53,14 @@ because the messagebus nonce in gateway locks a single message per staker - and the UXC contract address is the `staker` for the gateway contract. A UXC can be (re-)used for multiple gateways in parallel. -Assumptions: +#### Assumptions: - staking OST originates from a hardware wallet (currently no support for EIP-721) -Flow BrandedToken+Gateway: +#### Flow BrandedToken+Gateway: -1. User approves transfer of OST to composer `OST.approve(uxc, amount)` (SIGN1) -2. User requests stake from composer `uxc.requestStake(...)` (SIGN2) +1. User approves transfer of OST to composer `OST.approve(uxc, amount)` (USER_SIGN1) +2. User requests stake from composer `uxc.requestStake(...)` (USER_SIGN2) ```solidity // see more detailed pseudocode below @@ -68,21 +68,52 @@ function uxc:requestStake() { // move OST from user to uxc // uxc.requestStake(stakeVT, mintVBT); - // store struct with + // store StakeRequest struct with } ``` +3. Event from `VBT` contract `VBT:StakeRequested` is evaluated against the +minting policy of the Branded Token. A registered workers' key for the +VBT's organisation can sign the `stakeRequestHash`; the resulting signature +`(r, s, v)` is required to approve the stakeRequest in the VBT contract. (ORG_SIGN1) -## Rationale - -The rationale fleshes out the specification by describing what motivated the design and why particular design decisions were made. It should describe alternate designs that were considered and related work, e.g. how the feature is supported in other languages. The rationale may also provide evidence of consensus within the community, and should discuss important objections or concerns raised during discussion.--> +4. Facilitator can generate a secret and corresponding hashlock for +`gateway:stake`, however the staker is the composer `uxc`, +so the facilitator must call on `uxc.acceptStakeRequest(...)` (FACIL_SIGN1) -## Backwards Compatibility - -All OIPs that introduce backwards incompatibilities must include a section describing these incompatibilities and their severity. The OIP must explain how the author proposes to deal with these incompatibilities. OIP submissions without a sufficient backwards compatibility treatise may be rejected outright. +```solidity +// see more detailed pseudocode below +function uxc::acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1, _hashLock) +{ + // load sr = StakeRequests[_stakeRequestHash] + // require(VBT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); + // VBT.approve(sr.gateway, sr.mintVBT); + // GatewayI(sr.gateway).stake( + sr.mintVBT, + sr.beneficiary, + sr.gasPrice, + sr.gasLimit, + sr.nonce, + _hashLock + ); + + // remove stakeRequest struct +} +``` -## Test Cases - -Test cases for an implementation are mandatory for OIPs that are affecting consensus changes. Other OIPs can choose to include links to test cases if applicable. +#### Additional requirements + +Composer must also support +- `transferVT`, `approveVT` by `onlyOwner` +- `transferVBT`, `approveVBT` by `onlyOwner` +- `revertStakeRequest` for VBT +- `revertStake` for Gateway + +Composer can support +- `destroy` to selfdestruct, but be warned that it risks loss of funds if there +are ongoing VBT stake requests or gateway stake operations - on revert they +would refund the destroyed contract address. We can check minimally that the +composer has no balances and/or there are no ongoing stake requests +(optionally). ## Implementation @@ -114,17 +145,17 @@ contract GatewayComposer { uint256 _nonce ) onlyOwner - returns (uint256 stakedAmount_) + returns (bytes32 stakeRequestHash_) { require(_mintVBT == BT.convert(_stakeVT)); require(OST.transferFrom(msg.sender, this, _stakeVT)); OST.approve(VBT, _stakeVT); require(VBT.requestStake(_stakeVT, _mintVBT)); - stakeRequests[gateway] = StakeRequest({ + stakeRequests[_stakeRequestHash] = StakeRequest({ stakeVT: stakeVT, mintVBT: _mintVBT, - // gateway: _gateway, + gateway: _gateway, beneficiary: _beneficiary, gasPrice: _gasPrice, gasLimit: _gasLimit, @@ -132,7 +163,27 @@ contract GatewayComposer { }); } - function acceptStakeRequest() + function acceptStakeRequest( + bytes32 _stakeRequestHash, + bytes32 _r, + bytes32 _s, + uint8 _v, + bytes32 _hashLock + ) + returns (bytes32 messageHash_) + { + // load sr = StakeRequests[_stakeRequestHash] + // require(VBT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); + // VBT.approve(sr.gateway, sr.mintVBT); + require(GatewayI(sr.gateway).stake( + sr.mintVBT, + sr.beneficiary, + sr.gasPrice, + sr.gasLimit, + sr.nonce, + _hashLock + )); + } function transferVT(...) onlyOwner function approveVT(...) onlyOwner From 0e7e57635bda3f9fb6efb2c019b1a65b226b2d57 Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Mon, 17 Dec 2018 19:51:41 +0100 Subject: [PATCH 4/8] uxc: add discussion thread link and coauthors --- OIPS/oip-draft_ux_composer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OIPS/oip-draft_ux_composer.md b/OIPS/oip-draft_ux_composer.md index 43055c3..478f166 100644 --- a/OIPS/oip-draft_ux_composer.md +++ b/OIPS/oip-draft_ux_composer.md @@ -1,8 +1,8 @@ --- oip: title: -author: -discussions-to: +author: <@jasonklein, @abhayks1, Benjamin Bollen (@benjaminbollen)> +discussions-to: status: Draft type: created: <2018-11-28> From 32f7a373343bbf50713af0b8794c4a97ea019add Mon Sep 17 00:00:00 2001 From: Benjamin Bollen Date: Thu, 20 Dec 2018 11:44:19 +0100 Subject: [PATCH 5/8] uxc: update flow and pseudocode for facilitator bounty --- OIPS/oip-draft_ux_composer.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/OIPS/oip-draft_ux_composer.md b/OIPS/oip-draft_ux_composer.md index 478f166..7664c8d 100644 --- a/OIPS/oip-draft_ux_composer.md +++ b/OIPS/oip-draft_ux_composer.md @@ -76,7 +76,10 @@ minting policy of the Branded Token. A registered workers' key for the VBT's organisation can sign the `stakeRequestHash`; the resulting signature `(r, s, v)` is required to approve the stakeRequest in the VBT contract. (ORG_SIGN1) -4. Facilitator can generate a secret and corresponding hashlock for +4. Facilitator can call `gateway.bounty()` to know the active bounty amount, +and must call `OST.approve(uxc, bounty)`. This way the bounty + +5. Facilitator can generate a secret and corresponding hashlock for `gateway:stake`, however the staker is the composer `uxc`, so the facilitator must call on `uxc.acceptStakeRequest(...)` (FACIL_SIGN1) @@ -85,6 +88,11 @@ so the facilitator must call on `uxc.acceptStakeRequest(...)` (FACIL_SIGN1) function uxc::acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1, _hashLock) { // load sr = StakeRequests[_stakeRequestHash] + + // bounty = GatewayI(sr.gateway).bounty(); + // ost.transferFrom(msg.sender, this, bounty); + // ost.approve(st.gateway, bounty); + // require(VBT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); // VBT.approve(sr.gateway, sr.mintVBT); // GatewayI(sr.gateway).stake( @@ -173,6 +181,11 @@ contract GatewayComposer { returns (bytes32 messageHash_) { // load sr = StakeRequests[_stakeRequestHash] + + // bounty = GatewayI(sr.gateway).bounty(); + // ost.transferFrom(msg.sender, this, bounty); + // ost.approve(st.gateway, bounty); + // require(VBT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); // VBT.approve(sr.gateway, sr.mintVBT); require(GatewayI(sr.gateway).stake( From 3ddd104321f544b70752049a7642f680963a9729 Mon Sep 17 00:00:00 2001 From: abhay Date: Thu, 20 Dec 2018 21:01:54 +0530 Subject: [PATCH 6/8] Commit includes Renamed UXC - GC including OIP draft filename as well as wherever it's referenced. - OSTPrime flow as discussed from forum. - Rename VBT => BT - Small cleanup --- ...poser.md => oip-draft_gateway_composer.md} | 124 ++++++++++-------- 1 file changed, 71 insertions(+), 53 deletions(-) rename OIPS/{oip-draft_ux_composer.md => oip-draft_gateway_composer.md} (62%) diff --git a/OIPS/oip-draft_ux_composer.md b/OIPS/oip-draft_gateway_composer.md similarity index 62% rename from OIPS/oip-draft_ux_composer.md rename to OIPS/oip-draft_gateway_composer.md index 7664c8d..8a46b25 100644 --- a/OIPS/oip-draft_ux_composer.md +++ b/OIPS/oip-draft_gateway_composer.md @@ -1,6 +1,6 @@ --- oip: -title: +title: author: <@jasonklein, @abhayks1, Benjamin Bollen (@benjaminbollen)> discussions-to: status: Draft @@ -18,9 +18,9 @@ in turn requires the user to sign more independent transactions. We propose a composition pattern to combine actions across different contracts into fewer combined actions (requiring less signatures) for the user -through the use of an optional UX Composer contract. Such a UX Composer -contract should be transparant such that only the users intended actions -can be executed. +through the use of an optional Gateway Composer contract. Such a Gateway +composer contract should be transparant such that only the users intended +actions can be executed. ## Abstract @@ -40,18 +40,18 @@ interaction flows across multiple contracts. ## Specification -We can think of the UX composer as a macro automating user actions. Users can -remove their macros and deploy improved ones. +We can think of the Gateway composer as a macro automating user actions. Users +can remove their macros and deploy improved ones. -We detail a UX composer for a user who wants to stake OST +We detail a Gateway composer for a user who wants to stake OST in a Branded Token (BT) contract and following that stake the Branded Tokens into a gateway contract to mint the same amount as Utility Branded Tokens (UBT) on the sidechain to use within the application of the token. -Every staker deploys her own Gateway composer contract (UXC), +Every staker deploys her own Gateway composer contract, because the messagebus nonce in gateway locks a single message per staker - -and the UXC contract address is the `staker` for the gateway contract. -A UXC can be (re-)used for multiple gateways in parallel. +and the Gateway contract address is the `staker` for the gateway contract. +A Gateway composer can be (re-)used for multiple gateways in parallel. #### Assumptions: - staking OST originates from a hardware wallet (currently no support for @@ -59,33 +59,36 @@ A UXC can be (re-)used for multiple gateways in parallel. #### Flow BrandedToken+Gateway: -1. User approves transfer of OST to composer `OST.approve(uxc, amount)` (USER_SIGN1) -2. User requests stake from composer `uxc.requestStake(...)` (USER_SIGN2) +1. User approves transfer of OST to composer `OST.approve(gc, amount)` +(USER_SIGNATURE1) -```solidity -// see more detailed pseudocode below -function uxc:requestStake() +2. User requests stake from composer `gc.requestStake(...)` (USER_SIGNATURE2) + +```Solidity +// See more detailed pseudocode below +function gc:requestStake() { - // move OST from user to uxc - // uxc.requestStake(stakeVT, mintVBT); + // Move OST from user to gc + // gc.requestStake(stakeVT, mintBT); // store StakeRequest struct with } ``` -3. Event from `VBT` contract `VBT:StakeRequested` is evaluated against the +3. Event from `BT` contract `BT:StakeRequested` is evaluated against the minting policy of the Branded Token. A registered workers' key for the -VBT's organisation can sign the `stakeRequestHash`; the resulting signature -`(r, s, v)` is required to approve the stakeRequest in the VBT contract. (ORG_SIGN1) +BT's organisation can sign the `stakeRequestHash`; the resulting signature +`(r, s, v)` is required to approve the stakeRequest in the BT contract. (ORG_SIGN1) 4. Facilitator can call `gateway.bounty()` to know the active bounty amount, -and must call `OST.approve(uxc, bounty)`. This way the bounty +and must call `OST.approve(gc, bounty)`. 5. Facilitator can generate a secret and corresponding hashlock for -`gateway:stake`, however the staker is the composer `uxc`, -so the facilitator must call on `uxc.acceptStakeRequest(...)` (FACIL_SIGN1) +`gateway:stake`. However the staker is the composer `gc`, +so the facilitator must call on `gc.acceptStakeRequest(...)` +(FACILITATOR_SIGN1) -```solidity -// see more detailed pseudocode below -function uxc::acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1, _hashLock) +```Solidity +// See more detailed pseudocode below +function gc::acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1, _hashLock) { // load sr = StakeRequests[_stakeRequestHash] @@ -93,10 +96,10 @@ function uxc::acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1, _hashLock) // ost.transferFrom(msg.sender, this, bounty); // ost.approve(st.gateway, bounty); - // require(VBT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); - // VBT.approve(sr.gateway, sr.mintVBT); + // require(BT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); + // BT.approve(sr.gateway, sr.mintBT); // GatewayI(sr.gateway).stake( - sr.mintVBT, + sr.mintBT, sr.beneficiary, sr.gasPrice, sr.gasLimit, @@ -108,17 +111,31 @@ function uxc::acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1, _hashLock) } ``` +## Flow OSTPrime + + There is only a gateway contract (no BrandedToken contract) mapping (OST on Ethereum mainnet) -> (OSTPrime on sidechain). + So stake and mint of OSTPrime would just take two signatures from the user without the obvious need for a composer contract; + + Stake and Mint flow of OSTPrime will look like below: + + - OST.approve(gateway, amount) + - Gateway.stake(amount, ..., hashlock) + + Hashlock would have to be given to the user (assuming the user is not his own facilitator). We will evaluate this further. + #### Additional requirements -Composer must also support +Composer must also support Below functions: + - `transferVT`, `approveVT` by `onlyOwner` -- `transferVBT`, `approveVBT` by `onlyOwner` -- `revertStakeRequest` for VBT +- `transferBT`, `approveBT` by `onlyOwner` +- `revertStakeRequest` for BT - `revertStake` for Gateway Composer can support + - `destroy` to selfdestruct, but be warned that it risks loss of funds if there -are ongoing VBT stake requests or gateway stake operations - on revert they +are ongoing BT stake requests or gateway stake operations - on revert they would refund the destroyed contract address. We can check minimally that the composer has no balances and/or there are no ongoing stake requests (optionally). @@ -127,42 +144,43 @@ composer has no balances and/or there are no ongoing stake requests Sketch pieces of code to guide -```solidity +```Solidity contract GatewayComposer { constructor ( address _owner, eip20tokenI _ost, - ValueBackedI _brandedToken) + ValueBackedI _brandedToken + ) function requestStake( - /// amount in VT (Value Token, set to OST) + /// Amount in VT (Value Token, set to OST) uint256 _stakeVT, - /// expected amount in VBT - uint256 _mintVBT, - /// gateway to transfer VBT into + /// Expected amount in BT + uint256 _mintBT, + /// Gateway to transfer BT into address _gateway, - /// beneficiary address on the metablockchain + /// Beneficiary address on the metablockchain address _beneficiary, - /// gas price for facilitator fee in (U)BT + /// Gas price for facilitator fee in (U)BT uint256 _gasPrice, - /// gas limit for message passing + /// Gas limit for message passing uint256 _gasLimit, - /// messagebus nonce for staker - /// note: don't attempt to compute the nonce in UXC + /// Messagebus nonce for staker + /// Note: don't attempt to compute the nonce in GC uint256 _nonce ) onlyOwner returns (bytes32 stakeRequestHash_) { - require(_mintVBT == BT.convert(_stakeVT)); + require(_mintBT == BT.convert(_stakeVT)); require(OST.transferFrom(msg.sender, this, _stakeVT)); - OST.approve(VBT, _stakeVT); - require(VBT.requestStake(_stakeVT, _mintVBT)); + OST.approve(BT, _stakeVT); + require(BT.requestStake(_stakeVT, _mintBT)); stakeRequests[_stakeRequestHash] = StakeRequest({ stakeVT: stakeVT, - mintVBT: _mintVBT, + mintBT: _mintBT, gateway: _gateway, beneficiary: _beneficiary, gasPrice: _gasPrice, @@ -186,10 +204,10 @@ contract GatewayComposer { // ost.transferFrom(msg.sender, this, bounty); // ost.approve(st.gateway, bounty); - // require(VBT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); - // VBT.approve(sr.gateway, sr.mintVBT); + // require(BT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); + // BT.approve(sr.gateway, sr.mintBT); require(GatewayI(sr.gateway).stake( - sr.mintVBT, + sr.mintBT, sr.beneficiary, sr.gasPrice, sr.gasLimit, @@ -201,7 +219,7 @@ contract GatewayComposer { function transferVT(...) onlyOwner function approveVT(...) onlyOwner - function transferVBT(...) onlyOwner - function approveVBT(...) onlyOwner + function transferBT(...) onlyOwner + function approveBT(...) onlyOwner } ``` \ No newline at end of file From 669913c665dc5b90e354c08c8782eeeee98b7e42 Mon Sep 17 00:00:00 2001 From: abhayks1 Date: Thu, 3 Jan 2019 19:40:40 +0530 Subject: [PATCH 7/8] Commit includes small error fix --- OIPS/oip-draft_gateway_composer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OIPS/oip-draft_gateway_composer.md b/OIPS/oip-draft_gateway_composer.md index 8a46b25..0d08dc0 100644 --- a/OIPS/oip-draft_gateway_composer.md +++ b/OIPS/oip-draft_gateway_composer.md @@ -50,7 +50,7 @@ on the sidechain to use within the application of the token. Every staker deploys her own Gateway composer contract, because the messagebus nonce in gateway locks a single message per staker - -and the Gateway contract address is the `staker` for the gateway contract. +and the Gateway Composer (GC) address is the `staker` for the gateway contract. A Gateway composer can be (re-)used for multiple gateways in parallel. #### Assumptions: From 74c148c6c57efb313e5de44f70c099994c07ca37 Mon Sep 17 00:00:00 2001 From: abhayks1 Date: Thu, 3 Jan 2019 20:14:38 +0530 Subject: [PATCH 8/8] Updated Gateway composer case to Gateway Composer since it's noun. --- OIPS/oip-draft_gateway_composer.md | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/OIPS/oip-draft_gateway_composer.md b/OIPS/oip-draft_gateway_composer.md index 0d08dc0..34b761f 100644 --- a/OIPS/oip-draft_gateway_composer.md +++ b/OIPS/oip-draft_gateway_composer.md @@ -1,6 +1,6 @@ --- oip: -title: +title: author: <@jasonklein, @abhayks1, Benjamin Bollen (@benjaminbollen)> discussions-to: status: Draft @@ -19,7 +19,7 @@ in turn requires the user to sign more independent transactions. We propose a composition pattern to combine actions across different contracts into fewer combined actions (requiring less signatures) for the user through the use of an optional Gateway Composer contract. Such a Gateway -composer contract should be transparant such that only the users intended +Composer contract should be transparant such that only the users intended actions can be executed. ## Abstract @@ -40,18 +40,18 @@ interaction flows across multiple contracts. ## Specification -We can think of the Gateway composer as a macro automating user actions. Users +We can think of the Gateway Composer as a macro automating user actions. Users can remove their macros and deploy improved ones. -We detail a Gateway composer for a user who wants to stake OST +We detail a Gateway Composer for a user who wants to stake OST in a Branded Token (BT) contract and following that stake the Branded Tokens into a gateway contract to mint the same amount as Utility Branded Tokens (UBT) on the sidechain to use within the application of the token. -Every staker deploys her own Gateway composer contract, +Every staker deploys her own Gateway Composer contract, because the messagebus nonce in gateway locks a single message per staker - and the Gateway Composer (GC) address is the `staker` for the gateway contract. -A Gateway composer can be (re-)used for multiple gateways in parallel. +A Gateway Composer can be (re-)used for multiple gateways in parallel. #### Assumptions: - staking OST originates from a hardware wallet (currently no support for @@ -59,10 +59,11 @@ A Gateway composer can be (re-)used for multiple gateways in parallel. #### Flow BrandedToken+Gateway: -1. User approves transfer of OST to composer `OST.approve(gc, amount)` +1. User approves transfer of OST to Gateway Composer `OST.approve(gc, amount)` (USER_SIGNATURE1) -2. User requests stake from composer `gc.requestStake(...)` (USER_SIGNATURE2) +2. User requests stake from Gateway Composer `gc.requestStake(...)` +(USER_SIGNATURE2) ```Solidity // See more detailed pseudocode below @@ -82,7 +83,7 @@ BT's organisation can sign the `stakeRequestHash`; the resulting signature and must call `OST.approve(gc, bounty)`. 5. Facilitator can generate a secret and corresponding hashlock for -`gateway:stake`. However the staker is the composer `gc`, +`gateway:stake`. However the staker is the Gateway Composer `gc`, so the facilitator must call on `gc.acceptStakeRequest(...)` (FACILITATOR_SIGN1) @@ -114,7 +115,7 @@ function gc::acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1, _hashLock) ## Flow OSTPrime There is only a gateway contract (no BrandedToken contract) mapping (OST on Ethereum mainnet) -> (OSTPrime on sidechain). - So stake and mint of OSTPrime would just take two signatures from the user without the obvious need for a composer contract; + So stake and mint of OSTPrime would just take two signatures from the user without the obvious need for a Gateway Composer contract; Stake and Mint flow of OSTPrime will look like below: @@ -125,19 +126,19 @@ function gc::acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1, _hashLock) #### Additional requirements -Composer must also support Below functions: +Gateway Composer must also support Below functions: - `transferVT`, `approveVT` by `onlyOwner` - `transferBT`, `approveBT` by `onlyOwner` - `revertStakeRequest` for BT - `revertStake` for Gateway -Composer can support +Gateway Composer can support - `destroy` to selfdestruct, but be warned that it risks loss of funds if there are ongoing BT stake requests or gateway stake operations - on revert they would refund the destroyed contract address. We can check minimally that the -composer has no balances and/or there are no ongoing stake requests +Gateway Composer has no balances and/or there are no ongoing stake requests (optionally). ## Implementation