diff --git a/standards/B3.md b/standards/B3.md new file mode 100644 index 0000000..43280f8 --- /dev/null +++ b/standards/B3.md @@ -0,0 +1,228 @@ +# ERC948 Interface for Pull Requests - B3's Financial Transaction Business Process Protocol (FTBPP) +### Summary +A standard interface to be implemented by smart wallets that wish to allow pre-authorized pull requests. + +### Abstract +This standard defines an interface to pre-authorize payments in order to allow parties to fulfill the payment at a later date via a pull request. The approval/pull request mechanism is purposefully generalized so that it can be used for both recurring pull requests (subscriptions) and one-off pull requests. This standard allows for payment to occur in Ether, ERC20, ERC223 tokens. This should be integrated into future versions of smart wallets, allowing for a more seamless process. + +### Our Thoughts +The ability to support all types of pull requests, not only subscriptions, is of utmost importance. Subscription is just one subset of an abundance of use cases for pull requests. Therefore, because we cannot now predict all of the unique uses for pull requests, it is important to create a standard that is general, yet secure enough to allow creative developers to build upon without the need for creating a new standard. + +### Motivation +It is inconvenient for a user to make a push payment every time a payment is required. The legacy banking system supports automatic bill payment features, allowing users to preauthorize recurring payments, saving users both the time to make the payment and the hassle of remembering when payments are due. Until we reduce the friction of subscriptions on the ethereum blockchain, companies will have to choose between customer experience and a subscription monetization model. + +Finally, it is important that there is a standard interface for pull requests. Having a standard allows wallets to create a pleasant UI/UX for its users, allowing users to feel comfortable and safe while authorizing, rejecting, and managing their pull requests. + +## Specification + +### Definitions +* planID - a unique hash used to identify a pull request plan +* planAgent - the authorized address to initiate a specific pull request (planID) + +### Features +* The Smart Wallet Interface only handles the approval, revocation of approval, and transfer of the asset. Therefore, the interface allows the approved planAgent to handle the complexity of determining the quantity, type of asset, recurrence, etc.. Thus, by managing the core functionality shared by all pull requests, the interface is interoperable with all varieties of complex pull requests. +* Supports pull requests of Ether, ERC20, ERC223 tokens +* Directly transfers funds from owner of the smart wallet to recipient + +## Methods + +### approvePullRequest + +Called by the owner of the smart wallet. + +* @param planAgent - it is the address of a smart contract (possibly a core account too) +* @param recurrency - limits the number of times a planAgent can call ‘pull’ in a given period +* @param periodLength - specifies the length of a period +* @param numberOfPeriods - specifies the how many periods before expiring +* @param valuePerPull - limits the maximum amount of an asset that can be transferred at a time +* @param valuePerPeriod - limits the maximum amount of an asset that can be transferred at a period +* @param planValueLimit - limits the total amount of an asset that can be transferred throughout the whole life of the plan +* @param asset - address of an ERC token - 0x0 if ether +* return planID + +``` +function authorizePlan( + address planAgent, + uint recurrency, + uint periodLength, + uint numberOfPeriods, + uint valuePerPull, + uint valuePerPeriod, + uint planValueLimit, + address asset + ) public onlyOwner returns (bytes32 planID); +``` + +This function must calculate and return a unique planID from the terms of the pull request. The function then must save the (planID, planAgent) pair as approved for later queries + +### revokeApproval + +Called by the owner of the smart wallet + +* @param planAgent - the approved planAgent of the (planID, planAgent) pair that should have its approval revoked +* @param planID - the planID of the (planID, planAgent) pair that should have its approval revoked +* @return success - true if successfully revoked the approval of (planAgent, planID) pair + +``` +function revokeApproval (address planAgent, bytes32 planID) public; +``` + +Must revoke the approval of the (planID, planAgent) pair. + +### getPullRequest + +Function available for all agents of a process + +* @param planAgent - it is the address of a smart contract (possibly a core account too) +* @param planID - The unique hash used to identify the pull request +* @return recurrency - limits the number of times an planAgent can call ‘pull’ in a given period +* @return periodLength - specifies the length of a period +* @return numberOfPeriods - specifies the how many periods before expiring +* @return valuePerPull - limits the maximum amount of an asset that can be transferred at a time +* @return valuePerPeriod - limits the maximum amount of an asset that can be transferred at a period +* @return planValueLimit - limits the total amount of an asset that can be transferred throughout the whole life of the plan +* @return asset - address of an ERC token - 0x0 if ether + +``` +function authorizePlan( + address planAgent, + bytes32 planID + ) public view returns ( + uint recurrency, + uint periodLength, + uint numberOfPeriods, + uint valuePerPull, + uint valuePerPeriod, + uint planValueLimit, + address asset); +``` + +This function must return the terms for pullRequest pair (planAgent, planID). + +### pullRequest + +Called by the planAgent to initiate a pull request + +* @param planID - the planID of the pull request to execute +* @param recipient - address of the receiver of the payment +* @param amount - amount of eth to send to recipient + +``` +function pullRequest (bytes32 planID, address recipient, uint amount) external; +``` + +The function **must throw** if the (planID, msg.sender) pair is **not authorized** to make pull requests. + +### pullRequest + +Called by the planAgent to initiate a pull request + +* @param planID - the planID of the pull request to execute +* @param recipient - address of the receiver of the payment +* @param amount - amount of ERC20 or ERC223 tokens to send to recipient +* @param _token - address of the token to transfer + +``` +function pullRequest (bytes32 planID, address recipient, uint amount, address _token) external; +``` + +The function **must throw** if the (planID, msg.sender) pair is **not authorized** to make pull requests. + +### pullRequest + +Called by the planAgent to initiate a pull request + +* @param planID - the planID of the pull request to execute +* @param recipient - address of the receiver of the payment +* @param amount - amount of ERC223 tokens to send to recipient +* @param _token - address of the token to transfer +* @param data - transaction metadata + +``` +function pullRequest (bytes32 planID, address recipient, uint amount, address _token, bytes data) external; +``` + +The function **must throw** if the (planID, msg.sender) pair is **not authorized** to make pull requests. + +### pullRequest + +Called by the planAgent to initiate a pull request + +* @param planID - the planID of the pull request to execute +* @param recipient - address of the receiver of the payment +* @param _token - address of the ERC721 token to transfer +* @param tokenID - array of ERC721 token ID’s to transfer +* @param data - array of bytes metadata for each token transfer + +``` +function pullRequest (bytes32 planID, address recipient, address _token, uint256[] tokenIDs, bytes[] data) external; +``` + +The tokenID in position i of the tokenID array must correspond to the data in the ith position of the data array. + +The function **must throw** if the (planID, msg.sender) pair is **not authorized** to make pull requests. + +### isPullRequestApproved + +Called by anyone to check if a specific (planID, planAgent) pair is approved to initiate the a pull request + +* @param planID - the planID of the (planID, planAgent) pair to check the approval of +* @param planAgent - the planAgent of the (planID, planAgent) pair to check the approval of +* @return approved - return true if the (planID, planAgent) pair is approved by this smart wallet + +``` +function isPullRequestApproved(bytes32 planID, address planAgent) public returns (bool approved); +``` + +Must return true if the owner of this smart wallet has approved the (planID, planAgent) pair without more recently revoking the approval of the pair. + +## Events + +### pullRequestApproved + +``` +event PullRequestApproved(address indexed planAgent, bytes32 indexed planID); +``` + +Must emit when an (planID, planAgent) pair is approved by the owner + +### pullRequestCancelled + +``` +event PullRequestCancelled(address indexed planAgent, bytes32 indexed planID); +``` + +Must emit when an (planID, planAgent) pair has their approval revoked. + +### PullTransfer + +``` +event PullTransfer(address indexed planAgent, bytes32 indexed planID, address indexed to, uint amount, address asset); +``` + +Must emit on a successful pullRequest of Ether, ERC20 tokens, or ERC223 tokens + +### PullTransfer + +``` +event PullTransfer(address indexed planAgent, bytes32 indexed planID, address indexed to, uint256[] tokenID, address asset); +``` + +Must emit on a successful pullRequest of ERC721 tokens + +## Flow Diagrams + +### Ether + +![](https://github.com/Balanc3-Consensys/Protocol/blob/master/Screen%20Shot%202018-07-24%20at%2012.08.31%20PM.png) + +### Tokens + +![](https://github.com/Balanc3-Consensys/Protocol/blob/master/Screen%20Shot%202018-07-24%20at%2012.08.40%20PM.png) + +## Implementation + +WIP + + +***