-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OIP-draft Gateway UX Composer #6
Open
benjaminbollen
wants to merge
8
commits into
OpenST:master
Choose a base branch
from
benjaminbollen:uxc
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 6 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
8aaee4d
draft: initial motivation
benjaminbollen 1a6bf45
uxc: start specification
benjaminbollen c698415
uxc: complete first draft of specification; up for discussion
benjaminbollen 0e7e576
uxc: add discussion thread link and coauthors
benjaminbollen 32f7a37
uxc: update flow and pseudocode for facilitator bounty
benjaminbollen 3ddd104
Commit includes
abhayks1 669913c
Commit includes small error fix
abhayks1 74c148c
Updated Gateway composer case to Gateway Composer since it's noun.
abhayks1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,225 @@ | ||
--- | ||
oip: <to be assigned> | ||
title: <Gateway composer for Branded Token and Gateway> | ||
author: <@jasonklein, @abhayks1, Benjamin Bollen (@benjaminbollen)> | ||
discussions-to: <https://discuss.openst.org/t/uxcomposer-brandedtoken-gateway/53> | ||
status: Draft | ||
type: <Meta> | ||
created: <2018-11-28> | ||
--- | ||
|
||
## Simple Summary | ||
<!--"If you can't explain it simply, you don't understand it well enough." Provide a simplified and layman-accessible explanation of the OIP.--> | ||
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 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 | ||
actions can be executed. | ||
|
||
## Abstract | ||
<!--A short (~200 word) description of the technical issue being addressed.--> | ||
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 | ||
<!--The motivation is critical for OIPs that want to change the OpenST protocol. It should clearly explain why the existing protocol specification is inadequate to address the problem that the OIP solves. OIP submissions without sufficient motivation may be rejected outright.--> | ||
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 to multiple contracts. | ||
A composition contract can facilitate the user experience for common | ||
interaction flows across multiple contracts. | ||
|
||
## Specification | ||
<!--The technical specification should describe the syntax and semantics of any new feature. The specification should be detailed enough to allow competing, interoperable implementations.--> | ||
|
||
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 | ||
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, | ||
because the messagebus nonce in gateway locks a single message per staker - | ||
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 | ||
EIP-721) | ||
|
||
#### Flow BrandedToken+Gateway: | ||
|
||
1. User approves transfer of OST to composer `OST.approve(gc, amount)` | ||
(USER_SIGNATURE1) | ||
|
||
2. User requests stake from composer `gc.requestStake(...)` (USER_SIGNATURE2) | ||
|
||
```Solidity | ||
// See more detailed pseudocode below | ||
function gc:requestStake(<all-user-params>) | ||
{ | ||
// Move OST from user to gc | ||
// gc.requestStake(stakeVT, mintBT); | ||
// store StakeRequest struct with <all-user-params> | ||
} | ||
``` | ||
3. Event from `BT` contract `BT:StakeRequested` is evaluated against the | ||
minting policy of the Branded Token. A registered workers' key for the | ||
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(gc, bounty)`. | ||
|
||
5. Facilitator can generate a secret and corresponding hashlock for | ||
`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 gc::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(BT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); | ||
// BT.approve(sr.gateway, sr.mintBT); | ||
// GatewayI(sr.gateway).stake( | ||
sr.mintBT, | ||
sr.beneficiary, | ||
sr.gasPrice, | ||
sr.gasLimit, | ||
sr.nonce, | ||
_hashLock | ||
); | ||
|
||
// remove stakeRequest struct | ||
} | ||
``` | ||
|
||
## 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 Below functions: | ||
|
||
- `transferVT`, `approveVT` by `onlyOwner` | ||
- `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 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). | ||
|
||
## 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.--> | ||
Sketch pieces of code to guide | ||
|
||
```Solidity | ||
contract GatewayComposer { | ||
|
||
constructor ( | ||
address _owner, | ||
eip20tokenI _ost, | ||
ValueBackedI _brandedToken | ||
) | ||
|
||
function requestStake( | ||
/// Amount in VT (Value Token, set to OST) | ||
uint256 _stakeVT, | ||
/// Expected amount in BT | ||
uint256 _mintBT, | ||
/// Gateway to transfer BT into | ||
address _gateway, | ||
/// 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 GC | ||
uint256 _nonce | ||
) | ||
onlyOwner | ||
returns (bytes32 stakeRequestHash_) | ||
{ | ||
require(_mintBT == BT.convert(_stakeVT)); | ||
require(OST.transferFrom(msg.sender, this, _stakeVT)); | ||
OST.approve(BT, _stakeVT); | ||
require(BT.requestStake(_stakeVT, _mintBT)); | ||
|
||
stakeRequests[_stakeRequestHash] = StakeRequest({ | ||
stakeVT: stakeVT, | ||
mintBT: _mintBT, | ||
gateway: _gateway, | ||
beneficiary: _beneficiary, | ||
gasPrice: _gasPrice, | ||
gasLimit: _gasLimit, | ||
nonce: _nonce, | ||
}); | ||
} | ||
|
||
function acceptStakeRequest( | ||
bytes32 _stakeRequestHash, | ||
bytes32 _r, | ||
bytes32 _s, | ||
uint8 _v, | ||
bytes32 _hashLock | ||
) | ||
returns (bytes32 messageHash_) | ||
{ | ||
// load sr = StakeRequests[_stakeRequestHash] | ||
|
||
// bounty = GatewayI(sr.gateway).bounty(); | ||
// ost.transferFrom(msg.sender, this, bounty); | ||
// ost.approve(st.gateway, bounty); | ||
|
||
// require(BT.acceptStakeRequest(_stakeRequestHash, _ORG_SIGN1)); | ||
// BT.approve(sr.gateway, sr.mintBT); | ||
require(GatewayI(sr.gateway).stake( | ||
sr.mintBT, | ||
sr.beneficiary, | ||
sr.gasPrice, | ||
sr.gasLimit, | ||
sr.nonce, | ||
_hashLock | ||
)); | ||
} | ||
|
||
function transferVT(...) onlyOwner | ||
function approveVT(...) onlyOwner | ||
|
||
function transferBT(...) onlyOwner | ||
function approveBT(...) onlyOwner | ||
} | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@abhayks1 small error from replacing; "... and the Gateway Composer (GC) address is the
staker
for the gateway contract."There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
Also updated case of "Gateway composer" to "Gateway Composer" in some places.