-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit baaf59d
Showing
18 changed files
with
29,119 additions
and
0 deletions.
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,17 @@ | ||
node_modules | ||
.env | ||
.DS_Store | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
lerna-debug.log* | ||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json | ||
pids | ||
*.pid | ||
*.seed | ||
*.pid.lock | ||
artifacts | ||
cache | ||
store |
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,20 @@ | ||
# Stream | ||
|
||
> create a group that splits incoming money to members in realtime | ||
Learn more: https://stream.moneypipe.xyz | ||
|
||
![pipe.png](pipe_poster.png) | ||
|
||
--- | ||
|
||
# Contract | ||
|
||
Stream is a [minimal proxy contract](https://eips.ethereum.org/EIPS/eip-1167), which makes deployments affordable ($40 ~ $90). | ||
|
||
This repository is made up of 2 main files: | ||
|
||
1. [Stream.sol](contracts/Stream.sol): The core "Stream" contract that handles realtime money split handling | ||
2. [Factory.sol](contracts/Factory.sol): The factory that clones and deploys the core Stream contract | ||
|
||
> There's an additional [Test.sol](contracts/Test.sol) but it's just for testing purpose and is not included in the deployment. |
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,73 @@ | ||
[ | ||
{ | ||
"inputs": [], | ||
"stateMutability": "nonpayable", | ||
"type": "constructor" | ||
}, | ||
{ | ||
"anonymous": false, | ||
"inputs": [ | ||
{ | ||
"indexed": true, | ||
"internalType": "address", | ||
"name": "owner", | ||
"type": "address" | ||
}, | ||
{ | ||
"indexed": true, | ||
"internalType": "address", | ||
"name": "group", | ||
"type": "address" | ||
}, | ||
{ | ||
"indexed": false, | ||
"internalType": "string", | ||
"name": "title", | ||
"type": "string" | ||
} | ||
], | ||
"name": "ContractDeployed", | ||
"type": "event" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "string", | ||
"name": "title", | ||
"type": "string" | ||
}, | ||
{ | ||
"components": [ | ||
{ | ||
"internalType": "address", | ||
"name": "account", | ||
"type": "address" | ||
}, | ||
{ | ||
"internalType": "uint32", | ||
"name": "value", | ||
"type": "uint32" | ||
}, | ||
{ | ||
"internalType": "uint32", | ||
"name": "total", | ||
"type": "uint32" | ||
} | ||
], | ||
"internalType": "struct Stream.Member[]", | ||
"name": "members", | ||
"type": "tuple[]" | ||
} | ||
], | ||
"name": "genesis", | ||
"outputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "", | ||
"type": "address" | ||
} | ||
], | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
} | ||
] |
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,79 @@ | ||
[ | ||
{ | ||
"anonymous": false, | ||
"inputs": [ | ||
{ | ||
"indexed": false, | ||
"internalType": "address", | ||
"name": "src", | ||
"type": "address" | ||
} | ||
], | ||
"name": "Stored", | ||
"type": "event" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"components": [ | ||
{ | ||
"internalType": "address", | ||
"name": "account", | ||
"type": "address" | ||
}, | ||
{ | ||
"internalType": "uint32", | ||
"name": "value", | ||
"type": "uint32" | ||
}, | ||
{ | ||
"internalType": "uint32", | ||
"name": "total", | ||
"type": "uint32" | ||
} | ||
], | ||
"internalType": "struct Stream.Member[]", | ||
"name": "m", | ||
"type": "tuple[]" | ||
} | ||
], | ||
"name": "initialize", | ||
"outputs": [], | ||
"stateMutability": "nonpayable", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [], | ||
"name": "members", | ||
"outputs": [ | ||
{ | ||
"components": [ | ||
{ | ||
"internalType": "address", | ||
"name": "account", | ||
"type": "address" | ||
}, | ||
{ | ||
"internalType": "uint32", | ||
"name": "value", | ||
"type": "uint32" | ||
}, | ||
{ | ||
"internalType": "uint32", | ||
"name": "total", | ||
"type": "uint32" | ||
} | ||
], | ||
"internalType": "struct Stream.Member[]", | ||
"name": "", | ||
"type": "tuple[]" | ||
} | ||
], | ||
"stateMutability": "view", | ||
"type": "function" | ||
}, | ||
{ | ||
"stateMutability": "payable", | ||
"type": "receive" | ||
} | ||
] |
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,45 @@ | ||
[ | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "addr", | ||
"type": "address" | ||
} | ||
], | ||
"name": "withdrawFail1", | ||
"outputs": [], | ||
"stateMutability": "payable", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "addr", | ||
"type": "address" | ||
} | ||
], | ||
"name": "withdrawFail2", | ||
"outputs": [], | ||
"stateMutability": "payable", | ||
"type": "function" | ||
}, | ||
{ | ||
"inputs": [ | ||
{ | ||
"internalType": "address", | ||
"name": "addr", | ||
"type": "address" | ||
} | ||
], | ||
"name": "withdrawSuccess", | ||
"outputs": [], | ||
"stateMutability": "payable", | ||
"type": "function" | ||
}, | ||
{ | ||
"stateMutability": "payable", | ||
"type": "receive" | ||
} | ||
] |
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,19 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.4; | ||
//import 'hardhat/console.sol'; | ||
import "@openzeppelin/contracts/proxy/Clones.sol"; | ||
import "./Stream.sol"; | ||
contract Factory { | ||
event ContractDeployed(address indexed owner, address indexed group, string title); | ||
address immutable implementation; | ||
constructor() { | ||
implementation = address(new Stream()); | ||
} | ||
function genesis(string calldata title, Stream.Member[] calldata members) external returns (address) { | ||
address payable clone = payable(Clones.clone(implementation)); | ||
Stream s = Stream(clone); | ||
s.initialize(members); | ||
emit ContractDeployed(msg.sender, clone, title); | ||
return clone; | ||
} | ||
} |
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,29 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.4; | ||
//import 'hardhat/console.sol'; | ||
import "@openzeppelin/contracts/proxy/utils/Initializable.sol"; | ||
contract Stream is Initializable { | ||
event Stored(address src); | ||
struct Member { | ||
address account; | ||
uint32 value; | ||
uint32 total; | ||
} | ||
Member[] private _members; | ||
function initialize(Member[] calldata m) initializer public { | ||
for(uint i=0; i<m.length; i++) { | ||
_members.push(m[i]); | ||
} | ||
} | ||
receive () external payable { | ||
require(_members.length > 0, "1"); | ||
for(uint i=0; i<_members.length; i++) { | ||
Member memory member = _members[i]; | ||
(bool sent, ) = payable(address(member.account)).call{value: msg.value*member.value/member.total}(""); | ||
require(sent, "2"); | ||
} | ||
} | ||
function members() external view returns (Member[] memory) { | ||
return _members; | ||
} | ||
} |
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,16 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity ^0.8.4; | ||
contract Test { | ||
receive() external payable {} | ||
function withdrawFail1(address addr) external payable { | ||
bool success = payable(addr).send(address(this).balance); | ||
require(success, "ran out of gas"); | ||
} | ||
function withdrawFail2(address addr) external payable { | ||
payable(addr).transfer(address(this).balance); | ||
} | ||
function withdrawSuccess(address addr) external payable { | ||
(bool success,) = payable(address(addr)).call{value: address(this).balance }(""); | ||
require(success); | ||
} | ||
} |
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 @@ | ||
{"address":"0x5FbDB2315678afecb367f032d93F642f64180aa3"} |
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 @@ | ||
{"address":"0x8faBF08451B71d0Ac8859828130051C5D3f674fa"} |
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 @@ | ||
{"address":"0x5FbDB2315678afecb367f032d93F642f64180aa3"} |
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,64 @@ | ||
/** | ||
* @type import('hardhat/config').HardhatUserConfig | ||
*/ | ||
const fs = require('fs') | ||
const path = require('path') | ||
require('dotenv').config() | ||
require('@nomiclabs/hardhat-waffle') | ||
require('hardhat-abi-exporter'); | ||
require("hardhat-gas-reporter"); | ||
require('hardhat-contract-sizer'); | ||
require("@nomiclabs/hardhat-etherscan"); | ||
task("deploy", "deploys the contract", async (args, hre) => { | ||
const [deployer] = await hre.ethers.getSigners(); | ||
let Factory = await hre.ethers.getContractFactory('Factory'); | ||
let factory = await Factory.deploy(); | ||
await factory.deployed(); | ||
console.log("factory address", factory.address); | ||
await fs.promises.mkdir(path.resolve(__dirname, "./deployments"), { recursive: true }).catch((e) => {}) | ||
await fs.promises.writeFile(path.resolve(__dirname, `./deployments/${hre.network.name}.json`), JSON.stringify({ address: factory.address })) | ||
return factory; | ||
}) | ||
module.exports = { | ||
gasReporter: { | ||
currency: "USD", | ||
// gasPrice: 80, | ||
// gasPrice: 150, | ||
coinmarketcap: process.env.COINMARKETCAP_API_KEY, | ||
enabled: true, | ||
}, | ||
solidity: { | ||
version: "0.8.4", | ||
settings: { | ||
optimizer: { | ||
enabled: true, | ||
runs: 1000, | ||
}, | ||
} | ||
}, | ||
mocha: { | ||
timeout: 2000000000 | ||
}, | ||
networks: { | ||
hardhat: { | ||
chainId: 1337, | ||
timeout: 1000 * 60 * 60 * 24, // 1 day | ||
gas: 12000000, | ||
blockGasLimit: 0x1fffffffffffff, | ||
allowUnlimitedContractSize: true, | ||
}, | ||
rinkeby: { | ||
url: process.env.RINKEBY, | ||
timeout: 1000 * 60 * 60 * 24, // 1 day | ||
accounts: [process.env.RINKEBY_PRIVATE_KEY], | ||
}, | ||
mainnet: { | ||
timeout: 1000 * 60 * 60 * 24, // 1 day | ||
url: process.env.MAINNET, | ||
accounts: [process.env.MAINNET_PRIVATE_KEY], | ||
} | ||
}, | ||
etherscan: { | ||
apiKey: process.env.ETHERSCAN_API_KEY | ||
} | ||
}; |
Oops, something went wrong.