Skip to content
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

Make stream creation atomic #43

Draft
wants to merge 21 commits into
base: dev
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
e887ac6
start direct deposit
TomAFrench Mar 23, 2020
4d8877b
refactor: move stream creation methods to utils
TomAFrench Apr 9, 2020
feb46af
feat(react-app): remove text explaining the need for two transactions
TomAFrench May 28, 2020
0af1e69
refactor(contracts): remove unused Aztec contract imports
TomAFrench May 28, 2020
01bae36
test(contracts): update tests to handle direct deposit
TomAFrench May 28, 2020
1d341de
style: fix typo cancelation -> cancellation
TomAFrench Jun 3, 2020
4c636f7
feat(contract-artifacts): update to newest contract artifacts
TomAFrench Jun 3, 2020
d523065
build: migrate to ethers v5, bump bnc-onboard to 1.10.2
TomAFrench Jul 9, 2020
79e9bb4
chore: add BROWSER=none to env file
TomAFrench Jul 9, 2020
36e1447
fix: update Stream type to accurately reflect that timestamps are str…
TomAFrench Jul 9, 2020
6493bcf
refactor: split getting useTokenDetails into separate hook
TomAFrench Jul 9, 2020
5500a79
fix: add return type to changeSort function
TomAFrench Jul 9, 2020
d4792d0
test: add tests for return values on different StreamUtilities functions
TomAFrench Jul 21, 2020
459055e
style: Capitalise flexLink to make it clear it is a component
TomAFrench Jul 24, 2020
4783b7d
feat: pass proof approval signature to contract when creating stream
TomAFrench Jul 24, 2020
f99a4b5
feat: remove Transak
TomAFrench Jul 25, 2020
37c0774
feat: add proper proptypes / type definition to FlexLink component
TomAFrench Jul 25, 2020
086da7c
build: mass update of package versions
TomAFrench Jul 25, 2020
23ba478
fix: bump versions in contract-artifacts to fix CI issue
TomAFrench Jul 25, 2020
53f1ea0
CI: bump circleci to use current LTS node
TomAFrench Jul 25, 2020
2f2c872
CI: use same node version for testing
TomAFrench Jul 25, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
build:
working_directory: ~/repo
docker:
- image: circleci/node:10.18.1
- image: circleci/node:erbium
steps:
- checkout
- run:
Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
test:
working_directory: ~/repo
docker:
- image: circleci/node:10.18.1
- image: circleci/node:erbium
steps:
- restore_cache:
keys:
Expand Down
15 changes: 10 additions & 5 deletions packages/contract-artifacts/contracts/NoteStream.ts

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions packages/contract-artifacts/contracts/StreamUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ export default {
contractName: 'StreamUtilities',
abi: [],
bytecode:
'0x60556023600b82828239805160001a607314601657fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72315820b0c8047152ae625605cc7c7239b8e424dfb7a37caeb5490776c10883d23299b664736f6c634300050f0032',
'0x60556023600b82828239805160001a607314601657fe5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72315820c8f9a590281f6d9170e715b7aeb1810d2783e72d630d1643d60a3320a9751d7664736f6c634300050f0032',
deployedBytecode:
'0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72315820b0c8047152ae625605cc7c7239b8e424dfb7a37caeb5490776c10883d23299b664736f6c634300050f0032',
'0x73000000000000000000000000000000000000000030146080604052600080fdfea265627a7a72315820c8f9a590281f6d9170e715b7aeb1810d2783e72d630d1643d60a3320a9751d7664736f6c634300050f0032',
linkReferences: {},
deployedLinkReferences: {},
};
15 changes: 8 additions & 7 deletions packages/contract-artifacts/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,14 @@
"@babel/preset-env": "^7.9.0",
"@babel/preset-typescript": "^7.9.0",
"@typescript-eslint/eslint-plugin-tslint": "^2.27.0",
"eslint": "^5.15.3",
"eslint-config-airbnb-base": "^13.1.0",
"eslint-config-prettier": "^6.0.0",
"eslint-plugin-import": "^2.20.2",
"lint-staged": "^10.2.2",
"eslint": "^7.5.0",
"eslint-config-airbnb-base": "^14.2.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^3.1.4",
"lint-staged": "^10.2.11",
"shx": "^0.3.2",
"typescript": "^3.8.3"
"typescript": "^3.9.7"
},
"engines": {
"node": ">=8.3"
Expand Down Expand Up @@ -53,7 +54,7 @@
"build:types": "tsc --emitDeclarationOnly",
"clean": "shx rm -rf ./lib",
"has:changed": "bash ../monorepo-scripts/ci/hasChanged.sh contract-artifacts",
"lint": "eslint --config .eslintrc.js --ext .js,.ts . ",
"lint": "eslint --config .eslintrc.js --ext .ts . ",
"watch": "yarn build --watch"
},
"config": {
Expand Down
24 changes: 0 additions & 24 deletions packages/contracts/contracts/AZTEC/Imports.sol

This file was deleted.

74 changes: 39 additions & 35 deletions packages/contracts/contracts/NoteStream.sol
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
pragma solidity ^0.5.11;

import "@openzeppelin/contracts/lifecycle/Pausable.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import '@openzeppelin/contracts/lifecycle/Pausable.sol';
import '@openzeppelin/contracts/utils/ReentrancyGuard.sol';

import "./StreamUtilities.sol";
import './StreamUtilities.sol';

import "./Types.sol";
import './Types.sol';


/**
Expand Down Expand Up @@ -65,7 +65,7 @@ contract NoteStream is Pausable, ReentrancyGuard {
require(
msg.sender == streams[streamId].sender ||
msg.sender == streams[streamId].recipient,
"caller is not the sender or the recipient of the stream"
'caller is not the sender or the recipient of the stream'
);
_;
}
Expand All @@ -76,7 +76,7 @@ contract NoteStream is Pausable, ReentrancyGuard {
modifier onlyRecipient(uint256 streamId) {
require(
msg.sender == streams[streamId].recipient,
"caller is not the recipient of the stream"
'caller is not the recipient of the stream'
);
_;
}
Expand All @@ -85,7 +85,7 @@ contract NoteStream is Pausable, ReentrancyGuard {
* @dev Throws if the provided id does not point to a valid stream.
*/
modifier streamExists(uint256 streamId) {
require(streams[streamId].isEntity, "stream does not exist");
require(streams[streamId].isEntity, 'stream does not exist');
_;
}

Expand All @@ -94,7 +94,7 @@ contract NoteStream is Pausable, ReentrancyGuard {
constructor(address _aceContractAddress) public {
require(
_aceContractAddress != address(0x00),
"ACE contract is the zero address"
'ACE contract is the zero address'
);
aceContractAddress = _aceContractAddress;
nextStreamId = 1;
Expand Down Expand Up @@ -144,32 +144,43 @@ contract NoteStream is Pausable, ReentrancyGuard {
* Throws if the contract is not allowed to transfer enough tokens.
* Throws if there is a token transfer failure.
* @param recipient The address towards which the money is streamed.
* @param noteHash The note of a zkAsset to be streamed.
* @param proof The JoinSplit proof transfering a zkAsset to be streamed.
* @param tokenAddress The zkAsset to use as streaming currency.
* @param startTime The unix timestamp for when the stream starts.
* @param stopTime The unix timestamp for when the stream stops.
* @return The uint256 id of the newly created stream.
*/
function createStream(
address recipient,
bytes32 noteHash,
bytes memory proof,
bytes memory proofSignature,
address tokenAddress,
uint256 startTime,
uint256 stopTime
) public whenNotPaused returns (uint256) {
require(recipient != address(0x00), "stream to the zero address");
require(recipient != address(this), "stream to the contract itself");
require(recipient != msg.sender, "stream to the caller");
require(recipient != address(0x00), 'stream to the zero address');
require(recipient != address(this), 'stream to the contract itself');
require(recipient != msg.sender, 'stream to the caller');
require(
startTime >= block.timestamp, // solium-disable-line security/no-block-members
"start time before block.timestamp"
'start time before block.timestamp'
);
require(stopTime > startTime, 'Stream duration not greater than zero');

// Transfer the ZkAsset to the streaming contract
bytes32 streamNoteHash = StreamUtilities._processDeposit(
proof,
proofSignature,
aceContractAddress,
msg.sender,
recipient,
tokenAddress
);
require(stopTime > startTime, "Stream duration not greater than zero");

/* Create and store the stream object. */
uint256 streamId = nextStreamId;
streams[streamId] = Types.AztecStream({
noteHash: noteHash,
noteHash: streamNoteHash,
sender: msg.sender,
recipient: recipient,
startTime: startTime,
Expand All @@ -187,7 +198,7 @@ contract NoteStream is Pausable, ReentrancyGuard {
msg.sender,
recipient,
tokenAddress,
noteHash,
streamNoteHash,
startTime,
stopTime
);
Expand All @@ -200,27 +211,21 @@ contract NoteStream is Pausable, ReentrancyGuard {
bytes memory _proof1, // Dividend Proof
bytes memory _proof2, // Join-Split Proof
uint256 _streamDurationToWithdraw
)
public
nonReentrant
streamExists(streamId)
onlyRecipient(streamId)
{
) public nonReentrant streamExists(streamId) onlyRecipient(streamId) {
Types.AztecStream storage stream = streams[streamId];

// First check that this isn't a zero value withdrawal
require(_streamDurationToWithdraw > 0, "zero value withdrawal");
require(_streamDurationToWithdraw > 0, 'zero value withdrawal');

// Check that fraction to withdraw isn't greater than fraction of time passed
require(
stream.lastWithdrawTime.add(_streamDurationToWithdraw) <
block.timestamp, // solium-disable-line security/no-block-members
"withdraw is greater than allowed"
'withdraw is greater than allowed'
);

// Check that value of withdrawal matches the fraction given by the above timestamp
(, bytes memory _proof1OutputNotes) = StreamUtilities
._validateRatioProof(
bytes32 withdrawalNoteHash = StreamUtilities._validateRatioProof(
aceContractAddress,
_proof1,
_streamDurationToWithdraw,
Expand All @@ -232,7 +237,7 @@ contract NoteStream is Pausable, ReentrancyGuard {
bytes32 newNoteHash = StreamUtilities._processWithdrawal(
aceContractAddress,
_proof2,
_proof1OutputNotes,
withdrawalNoteHash,
stream
);

Expand Down Expand Up @@ -283,7 +288,7 @@ contract NoteStream is Pausable, ReentrancyGuard {
}

// We require the denominator of ratio proof to be nonzero
require(_unclaimedTime > 0, "cancellation with zero unclaimed time");
require(_unclaimedTime > 0, 'cancellation with zero unclaimed time');

// Otherwise check that cancelling party isn't trying to scam the other
// Each party can only cancel from a timestamp favourable to the other party.
Expand All @@ -296,20 +301,19 @@ contract NoteStream is Pausable, ReentrancyGuard {
stream.lastWithdrawTime.add(_unclaimedTime) > block.timestamp ||
stream.lastWithdrawTime.add(_unclaimedTime) ==
stream.stopTime,
"sender receives too much from cancellation"
'sender receives too much from cancellation'
);
} else if (msg.sender == stream.recipient) {
// Recipient can only cancel from a timestamp which has already passed
require(
// solium-disable-next-line security/no-block-members
stream.lastWithdrawTime.add(_unclaimedTime) < block.timestamp,
"recipient receives too much from cancellation"
'recipient receives too much from cancellation'
);
}

// Check that value of withdrawal matches the fraction given by the above timestamp
(, bytes memory _proof1OutputNotes) = StreamUtilities
._validateRatioProof(
bytes32 withdrawalNoteHash = StreamUtilities._validateRatioProof(
aceContractAddress,
_proof1,
_unclaimedTime,
Expand All @@ -318,10 +322,10 @@ contract NoteStream is Pausable, ReentrancyGuard {

// Check that cancellation transaction is valid and perform transfer
// i.e. Each party receives a note of correct value
StreamUtilities._processCancelation(
StreamUtilities._processCancellation(
aceContractAddress,
_proof2,
_proof1OutputNotes,
withdrawalNoteHash,
stream
);

Expand Down
Loading