diff --git a/demo.sol b/demo.sol new file mode 100644 index 0000000..01c159d --- /dev/null +++ b/demo.sol @@ -0,0 +1,60 @@ +/** + *Submitted for verification at FtmScan.com on 2021-09-19 +*/ +// SPDX-License-Identifier: MIT + +/** + * 合约的安全性已经被FTMSCAN验证并且公开 + * 代码非常简洁,目的就是为了帮助大家节省Gas费用 + * 社区:https://futureworld.app + * 作者:冈本聪 +*/ + +pragma solidity 0.8.7; + + +/** + * 以下的内容除了 ‘test’函数外,其余都建议保留。 + * 如遇到不懂可在技术群寻求支持 +*/ +interface iProjectAPI{ + function viewUserPay(uint _pid,address _user) external view returns (address user,string memory item,uint payTime,uint money,bool status); //查询用户付款信息 + function projectContractPay(uint _pid ,address _user,string memory _item,uint _amount) external returns(bool) ; + function viewMyID() external view returns(uint) ; //查询自己的ID +} + + +contract Demo { + address private admin ; + address projectApiAddr = 0x2474E374Db782bB3A609f6109A40EE366B6cD747 ; // projectAPI合约地址 + iProjectAPI projectAPI = iProjectAPI(projectApiAddr); //引用合约 + uint public myID ; + + + function testpay() public payable returns (bool) { + require(msg.value > 0) ; + bool status = payable(projectApiAddr).send(msg.value); + if(status) projectAPI.projectContractPay(myID,msg.sender,'item-1',msg.value) ; + return status ; + } + + function testPayInfo() public view returns (address user,string memory item,uint payTime,uint money,bool status) { + return projectAPI.viewUserPay(myID,msg.sender) ; + } + + constructor(address _admin){ + admin = _admin ; + } + + function confirmProject() public onlyAdmin { + myID = projectAPI.viewMyID() ; + } + + + modifier onlyAdmin(){ + require(msg.sender == admin ); + _; + } + + +} \ No newline at end of file diff --git a/projectAPI.sol b/projectAPI.sol new file mode 100644 index 0000000..c2eedc3 --- /dev/null +++ b/projectAPI.sol @@ -0,0 +1,183 @@ +/** +* 该合约是与开发者Dapp进行接口交互的合于。用途如下: +* 1. Dapp收费后再分配 +* 2. 帮助项目进行初步的合约审核,社区宣传 +* 3. 记录社区成员是否付费 +* https://futureworld.app +* 未来世界DAO 社区发起人:冈本聪 +*/ + + +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.7; + +import "./safemath.sol" ; + +contract projectsAPI { + using SafeMath for uint256 ; + + //社区相关信息 + address public fundAddress ; //资金会收款地址 + address public admin ; + + //项目方需要的相关变量和数据 + uint public PID = 1 ; //项目的ID + mapping (uint => project) public Projects; // 项目ID => 项目信息 + mapping (uint => address) public projectOwner; //项目的所有者 + mapping (address => uint[]) public myProjects ; //持有者所有项目列表 + mapping (address => uint) private queryID ; //合约 => 项目ID + + //用户付费相关 + mapping (uint => mapping(address => payInfo)) public payInformation ; // 项目ID=>用户=>支付信息 + + //相关资金问题 + uint private projectPercent = 80 ; //项目方分成比例 + mapping(address=>uint) public projectBalance ; //项目方的收入 + uint public fundationBalance ; //社区基金会 + + //项目信息 + struct project { + string name; //项目名称 + string intro; //项目简介 + string link ; //Dapp网站 + address wallet ; //收款地址 + string chain ; //主链名称(FTM,BSC....等) + address contract_ ; //Dapp contract + string tag ; //项目的类型 + uint8 status ; //“1”表示 待审核,“2”表示审核通过,“3”表示拒绝 + uint profitPercent ; //项目方的利润比例 + } + + //付款人信息 + struct payInfo{ + address user ; //付款人 + string item ; //付费的具体类目 + uint payTime ; //支付时间 + uint money ; //支付金额 + bool status ; //付费状态 + } + + constructor(address _admin,address _fundAddress) { + admin = _admin ; //管理员 + fundAddress = _fundAddress ; //资金会的地址 + } + + //合约中用户支付查询 + function viewUserPay(uint _pid,address _user) external view returns (address user,string memory item,uint payTime,uint money,bool status) { + user = payInformation[_pid][_user].user ; + item = payInformation[_pid][_user].item ; + payTime = payInformation[_pid][_user].payTime ; + money = payInformation[_pid][_user].money ; + status = payInformation[_pid][_user].status ; + return (user,item,payTime,money,status) ; + } + + //管理员修改项目信息 + function modifyAdminInfo(address _admin, address _fundAddress,uint _projectPercent) public onlyAdmin { + admin = _admin ; //管理员 + fundAddress = _fundAddress ; //资金会的地址 + projectPercent = _projectPercent; // Dapp开发方分成 + } + + //社区资金会提款 + function fundationWithdraw() public { + require(msg.sender == fundAddress ,"You can not do that!!!") ; + payable(fundAddress).transfer(fundationBalance) ; + fundationBalance = 0 ; + } + + //项目方提款 + function projectWidraw(uint _pid) external onlyProjectOwner(_pid) { + address wallet = Projects[_pid].wallet ; + payable(wallet).transfer(projectBalance[wallet]) ; + projectBalance[wallet] = 0 ; + } + + receive() external payable { + + } + + //资金分配 + function _fundAllocation(uint _money,address _projectOwner) internal { + projectBalance[_projectOwner] += (_money.mul(projectPercent)).div(100) ; + fundationBalance += (_money - (_money.mul(projectPercent)).div(100)) ; + } + + //项目合约调用查询自己的ID + function viewMyID() external view returns(uint) { + require(_isContract(msg.sender)); + return queryID[msg.sender] ; + } + + //项目方收钱接口 + function projectContractPay(uint _pid ,address _user,string memory _item,uint _amount) external returns (bool) { //开发者合约调用,huo'zhe。 + require(_isContract(msg.sender) && Projects[_pid].contract_ == msg.sender && Projects[_pid].status == 2) ; + payInformation[_pid][_user] = payInfo(_user,_item, block.timestamp, _amount,true) ; + _fundAllocation(_amount,Projects[_pid].wallet); + return true ; + } + + //前端web方式收款 + function projectWebPay(uint _pid,string memory _item) public payable { + require(msg.sender != address(0)) ; + require(msg.value > 0) ; + payInformation[_pid][msg.sender] = payInfo(msg.sender,_item, block.timestamp, msg.value,true) ; + _fundAllocation(msg.value,Projects[_pid].wallet); + } + + //开发者申请项目提交 + function supplyProject(string memory _name,string memory _intro,string memory _link,address _wallet,string memory _chain,address _contract,string memory _tag) external returns(uint myID) { + require(msg.sender != address(0)) ; + require(queryID[_contract] == 0 ) ; + Projects[PID] = project(_name,_intro,_link,_wallet,_chain,_contract,_tag,1,projectPercent) ; + projectOwner[PID] = msg.sender ; + myProjects[msg.sender].push(PID) ; + queryID[_contract] = PID ; + myID = PID ; + PID++ ; + return myID ; + } + + //管理员修改项目信息 + function adminMofityProject(uint _pid,string memory _tag,uint8 _status) public onlyAdmin { + string memory name = Projects[_pid].name ; + string memory intro = Projects[_pid].intro ; + string memory link = Projects[_pid].link ; + string memory chain = Projects[_pid].chain ; + address wallet = Projects[_pid].wallet ; + address contract_ = Projects[_pid].contract_ ; + uint percent = Projects[_pid].profitPercent ; + Projects[_pid] = project(name,intro,link,wallet,chain,contract_,_tag,_status,percent) ; + } + + //判断是否为合约地址 + function _isContract(address account) internal view returns (bool) { + uint256 size; + assembly { + size := extcodesize(account) + } + return size > 0; + } + + //项目方修改项目信息,适用于发布,升级合约 + function modifyProject(uint _pid ,string memory _name,string memory _intro,string memory _link,address _wallet,string memory _chain,address _contract,string memory _tag) external onlyProjectOwner(_pid){ + require(msg.sender != address(0)) ; + uint percent = Projects[_pid].profitPercent ; + queryID[_contract] = _pid ; + Projects[_pid] = project(_name,_intro,_link,_wallet,_chain,_contract,_tag,1,percent) ; + } + + //社区管理员(没有具体的人,而是约束的某个合约)修改 + modifier onlyAdmin { + require(admin == msg.sender) ; + _; + } + + modifier onlyProjectOwner(uint _pid) { + require (projectOwner[_pid] == msg.sender); + _; + } + + + +} diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..4e16903 --- /dev/null +++ b/readme.md @@ -0,0 +1,62 @@ +![](http://futureworld.com/web/assets/img/logo-button.png) + +[TOC] + + +## 简介 + +> projectAPI.sol 是“未来世界”DAO社区与开发者Dapp最核心的环节,它决定了社区的共识、帮助项目推广利润分配等问题。操作步骤如下。 + + +## 第一步:创建你的Dapp合约 +创建合约,在合约中引入demo.sol中的相关内容,除函数 test()之外,其余的如果对合约内容不够熟悉的最好全部保留,也可以根据您进行灵活配置。创建好你的合约合约。 +> tips:可以将`projectAPI.sol`文件复制到本地进行调试与各项测试。 + + +## 第二步 向社区`projectAPI.sol`提交你的项目申请 +项目简介在[0x758a50c5dca4611d35a80f304aa1c1092ba09c1d](https://ftmscan.com/address/0x758a50c5dca4611d35a80f304aa1c1092ba09c1d "0x758a50c5dca4611d35a80f304aa1c1092ba09c1d")中找到函数`supplayProject()`,提交项目的相关资料。资料包括`项目名称`,`项目简介`,`合约地址`,`收款地址`等等。 + + +> tips:调用成功后联系社区相关工作人员进行进行合约审核。 + +## 第三步 在你的合约中调用`confirmProject()` 确认身份 +## 其他问题 +### 查询用户付费 + +- **solidity** +``` solidity + projectAPI.viewUserPay(uint _pid,address _user); +``` + +- **javascript** +```javascript +contract.methods.payInformation('你的ID','用户地址','收费类目').call(function(s,r){ + if(s==null && r.status) { + //执行你的代码.... + } +}) +``` + +### 向用户发起付费 +- **solidity** +``` solidity + function test() public payable { + require(msg.value > 0) ; + projectAPI.projectContractPay(myID,msg.sender,'item-1') ; //在合约中记录该笔用户记录 + payable(projectApiAddr).transfer(msg.value) ; //将资金转移到合约中再分配(可随时提现) + } +``` +- **javascript** +```javascript +contract.methods.projectWebPay(uint _pid,string memory _item).send({from:address}).on('confirmation',function(){ + //在链上确认后执行相关你的代码 +}) +``` + +### 提款 +在[0x758a50c5dca4611d35a80f304aa1c1092ba09c1d](https://ftmscan.com/address/0x758a50c5dca4611d35a80f304aa1c1092ba09c1d "0x758a50c5dca4611d35a80f304aa1c1092ba09c1d")中找到`projectWidraw(uint _pid)`进行提款即可,需要注意的是你必须用在supplyProject发起申请的地址才能够进行取款。 + +> tips:在合约中一共留下了3个地址。一个是你提交申请地址(项目管理)。一个是收款的钱包地址(用户收款)。一个是你的合约地址(用于再次确认是否属于您本人) + + + diff --git a/safemath.sol b/safemath.sol new file mode 100644 index 0000000..5167f27 --- /dev/null +++ b/safemath.sol @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.7; + + +library SafeMath { + /** + * @dev Returns the addition of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `+` operator. + * + * Requirements: + * + * - Addition cannot overflow. + */ + function add(uint256 a, uint256 b) internal pure returns (uint256) { + uint256 c = a + b; + require(c >= a, "SafeMath: addition overflow"); + return c; + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b) internal pure returns (uint256) { + return sub(a, b, "SafeMath: subtraction overflow"); + } + + /** + * @dev Returns the subtraction of two unsigned integers, reverting with custom message on + * overflow (when the result is negative). + * + * Counterpart to Solidity's `-` operator. + * + * Requirements: + * + * - Subtraction cannot overflow. + */ + function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b <= a, errorMessage); + uint256 c = a - b; + + return c; + } + + /** + * @dev Returns the multiplication of two unsigned integers, reverting on + * overflow. + * + * Counterpart to Solidity's `*` operator. + * + * Requirements: + * + * - Multiplication cannot overflow. + */ + function mul(uint256 a, uint256 b) internal pure returns (uint256) { + // Gas optimization: this is cheaper than requiring 'a' not being zero, but the + // benefit is lost if 'b' is also tested. + // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 + if (a == 0) { + return 0; + } + + uint256 c = a * b; + require(c / a == b, "SafeMath: multiplication overflow"); + + return c; + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b) internal pure returns (uint256) { + return div(a, b, "SafeMath: division by zero"); + } + + /** + * @dev Returns the integer division of two unsigned integers. Reverts with custom message on + * division by zero. The result is rounded towards zero. + * + * Counterpart to Solidity's `/` operator. Note: this function uses a + * `revert` opcode (which leaves remaining gas untouched) while Solidity + * uses an invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b > 0, errorMessage); + uint256 c = a / b; + // assert(a == b * c + a % b); // There is no case in which this doesn't hold + + return c; + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b) internal pure returns (uint256) { + return mod(a, b, "SafeMath: modulo by zero"); + } + + /** + * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), + * Reverts with custom message when dividing by zero. + * + * Counterpart to Solidity's `%` operator. This function uses a `revert` + * opcode (which leaves remaining gas untouched) while Solidity uses an + * invalid opcode to revert (consuming all remaining gas). + * + * Requirements: + * + * - The divisor cannot be zero. + */ + function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { + require(b != 0, errorMessage); + return a % b; + } +} \ No newline at end of file