多签存证合约功能
1. 编写多签存证接口和存证合约
pragma solidity^0.8.7;
interface IEvidence{
//验证某个人是否具有签名资格
function verify(address _signer) external view returns(bool);
//根据编号查看某个人的具体签名信息
function getSigner(uint256 _index)external view returns(address);
//查看所有人的签名信息
function getAllSigner()external view returns(address[] memory);
//查看需要签名的用户数量
function getSignersSize()external view returns(uint256);
}
contract Evidence{
//数据定义
string evidence;
address[] signers;//已签过名列表
address public factoryAddr;//工厂合约接口地址
event NewSignaturesEvidence(string _evi,address _sender);
event AddRepeatSignatureEvidence(string _evi,address _sender);
event AddSignatureEvidence(string _evi,address _sender);
//验证调用合约的人是否具有签名的资格
function callVerify(address _signer) public view returns(bool){
return IEvidence(factoryAddr).verify(_signer);
}
//function
constructor(string memory _evi,address _factory){
factoryAddr=_factory;
//此处不能使用msg.sender,因为A合约调用B合约,B合约中的msg.sender是A合约的地址,而不是调用合约的账户地址,tx.origin交易的原始发起者
require(callVerify(tx.origin),"_signer is not valid!");
//记录存证信息
evidence=_evi;
//存入签名列表中
signers.push(tx.origin);
emit NewSignaturesEvidence(_evi,tx.origin);
}
//查看某个存证信息,具体包括存证数据,待签名列表,已签名列表
function getEvidence() public view returns(string memory,address[] memory,address[] memory){
uint256 isize = IEvidence(factoryAddr).getSignersSize();
address[] memory signerList= new address[](isize);
for(uint256 i=0;i<isize;i++){
signerList[i]=IEvidence(factoryAddr).getSigner(i);
}
return(evidence,signerList,signers);
}
//查看所有存证信息,具体包括存证数据,待签名列表,已签名列表
function getAllEvidence() public view returns(string memory,address[] memory,address[] memory){
uint256 isize = IEvidence(factoryAddr).getSignersSize();
address[] memory signerList= new address[](isize);
for(uint256 i=0;i<isize;i++){
signerList[i]=IEvidence(factoryAddr).getSigner(i);
}
return(evidence,signerList,signers);
}
//签名
function sign()public returns(bool){
//判断该人是否有签名资格
require(callVerify(tx.origin),"_signer is not valid!");
//该人是否已经签过名
if(isSigned(tx.origin)){
emit AddRepeatSignatureEvidence(evidence,tx.origin);
return true;
}
signers.push(tx.origin);
emit AddSignatureEvidence(evidence,tx.origin);
return true;
}
//验证是否已经签过名
function isSigned(address _signer)internal view returns(bool){
for(uint256 i=0;i<signers.length;i++){
if(signers[i]==_signer){
return true;
}
}
return false;
}
//是否所有人都已签过名
function isAllSigned()public view returns(bool,string memory){
uint256 isize = IEvidence(factoryAddr).getSignersSize();
for(uint256 i=0;i<isize;i++){
if(!isSigned(IEvidence(factoryAddr).getSigner(i))){
return(false,"");
}
}
return(true,evidence);
}
}
2. 编写工厂合约
pragma solidity^0.8.7;
import "./Evidence.sol";
contract EvidenceFactory is IEvidence{
mapping(string=>address) evi_keys; //记录若干个存证合约信息
address[] signers; //签名列表
//记录存证合约信息,存证合约的创建者,存证合约地址
event NewEvidence(string _evi,address _sender,address _eviAddr);
constructor(address[]memory _signers){
for(uint256 i=0;i<_signers.length;i++){
signers.push(_signers[i]);
}
}
//验证某个人是否具有签名资格
function verify(address _signer)override external view returns(bool){
for(uint256 i=0;i<signers.length;i++){
if(signers[i]==_signer){
return true;
}
}
return false;
}
//根据编号查看某个人的具体签名信息
function getSigner(uint256 _index) override external view returns(address){
if(_index<signers.length){
return signers[_index];
}else{
return address(0);
}
}
//查看所有人的签名信息
function getAllSigner() override external view returns(address[] memory){
return signers;
}
//查看需要签名的用户数量
function getSignersSize() override external view returns(uint256){
return signers.length;
}
//创建存证 ,第二个参数是为了记录存证合约地址,有了地址,才可以进行后续操作
function newEvidence(string memory _evi,string memory _key)public returns(address){
Evidence evidence = new Evidence(_evi,address(this));
evi_keys[_key] = address(evidence); //强制类型转换
emit NewEvidence(_evi,msg.sender, address(evidence));
return address(evidence);
}
//查询存证
function getEvidence(string memory _key)public view returns(string memory,address[] memory,address[] memory){
address addr = evi_keys[_key];
return Evidence(addr).getEvidence();
}
//签名方法
function sign(string memory _key)public returns(bool){
address addr = evi_keys[_key];
return Evidence(addr).sign();
}
//是否所有都签名
function isAllSigned(string memory _key) public view returns(bool,string memory){
address addr = evi_keys[_key];
return Evidence(addr).isAllSigned();
}
}
3.测试
部署工厂合约,初始化需要签名的列表
1. 查看需要签名的人数
2. 查看某个签名信息
3. 查看所有签名信息
4.创建存证
5.查询存证信息
包含存证信息,待签名列表,已签名列表,创建存证的人默认已经签名
6.签名
使用未在签名列表的账户进行签名
出现以下错误
使用正确的账户进行签名
查询存证信息,已经2人签名
7.查看是否全部签名
注意
//此处不能使用msg.sender,因为A合约调用B合约,B合约中的msg.sender是A合约的地址,而不是调用合约的账户地址,tx.origin交易的原始发起者
require(callVerify(tx.origin),"_signer is not valid!");