前提
Ownable:监管者合约,有一个函数能转让监管者。
SupplyChainFin:供应链金融合约,银行、公司信息上链,公司和银行之间的转账。
发票:记录者交易双方和交易金额等的一种记录数据。如:我在超市买了一瓶水,超市给我开了一张发票。
Ownable
javascript
// SPDX-License-Identifier: MIT
pragma solidity >=0.4 <=0.9;
/*
*@title Ownable
*@dev
*/
contract Ownable{
address public owner; // 监管者
event OwnershipTransferred( // 监管者转让结构体
address indexed priviousOwner, // indexed表名可以被索引
address indexed newOwner
);
constructor() {
owner = msg.sender;
}
// 判断用户是否是监管者
modifier onlyOwner(){
require(msg.sender == owner,"You cannot owner!");
_;
}
// 转让所有权,必须是原先监管者转让
function transferOwnership(address newOwner) public onlyOwner{
require(newOwner != owner && newOwner != address(0),"newOwner cannot be empty and equal to the priviousOwner");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
SupplyChainFin
javascript
// SPDX-License-Identifier: MIT
pragma solidity >=0.4 <=0.9;
import "./Ownable.sol";
/**
*@title SuppluChainFin
*@dev
*/
contract SupplyChainFin is Ownable{
// 监管者信息结构体
struct Supervisor{
string supervisorName;
address supervisorAddress;
}
// 公司信息结构体
struct Company{
string companyName;
address companyAddress;
uint creditAsset;
uint[] acceptReceiptIndex;
uint[] sendReceiptIndex;
}
// 银行信息结构体
struct Bank{
string bankName;
address bankAddress;
uint creditAsset;
uint[] acceptReceiptIndex;
uint[] sendReceiptIndex;
}
// 数字发票收据信息
struct Receipt {
address senderAddress;
address accepterAddress;
uint8 receiptType; // 发票类型
uint8 transferType; // 转账类型
uint amount; // 交易额
}
// 公司的map ,用于快速搜索
mapping(address => Company) companyMap;
// 银行map
mapping (address =>Bank) bankMap;
// 发票的map
mapping (uint => Receipt) receiptMap;
//监管者实体
Supervisor public supervisor;
// 公司地址的数组
address[] public companies;
// 银行地址的数组
address[] public banks;
//数组发票索引
uint public receiptIndex;
constructor(string memory name){
supervisor = Supervisor(name,msg.sender); // 初始化监管者信息
}
// 将公司信息添加到智能合约中
function addCompany(
string memory name,
address companyAddress
)public payable returns(bool){
// 初始化公司结构体
// 添加到公司map
// 添加到公司数组
Company memory newCompany = Company(
name,
companyAddress,
msg.value,
new uint[](0),
new uint[](0)
);
companyMap[companyAddress] = newCompany;
companies.push(companyAddress);
return true;
}
// 获取公司信息
function getCompany(
address companyAddress
) public view returns(string memory,address,uint,uint[] memory,uint[] memory){
// 用地址拿出公司结构体
// 将需要的数据一起返回
Company memory company = companyMap[companyAddress];
return (
company.companyName,
company.companyAddress,
company.creditAsset,
company.acceptReceiptIndex,
company.sendReceiptIndex
);
}
// 添加银行信息上链
function addBank(
string memory bankName,
address bankAddress
) public payable returns(bool){
Bank memory newBank;
newBank.bankName = bankName;
newBank.bankAddress = bankAddress;
newBank.creditAsset = msg.value;
bankMap[bankAddress] = newBank;
banks.push(bankAddress);
return true;
}
// 获取银行信息
function getBank(
address bankAddress
) public view returns(string memory,address,uint,uint[] memory,uint[] memory){
Bank memory bank = bankMap[bankAddress];
return (
bank.bankName,
bank.bankAddress,
bank.creditAsset,
bank.acceptReceiptIndex,
bank.sendReceiptIndex
);
}
// 获取公司全部地址
function getAllCompanyAddress() public view returns(address[] memory){
return companies;
}
// 获取银行全部地址
function getAllBankAddress() public view returns(address[] memory){
return banks;
}
// 获取凭证
function getRecipt(
uint index
)public view returns(address,address,uint8,uint8,uint){
Receipt memory receipt = receiptMap[index];
return (
receipt.senderAddress,
receipt.accepterAddress,
receipt.receiptType,
receipt.transferType,
receipt.amount
);
}
//存证交易
// receiptType: 发票类型(存证、现金)
//1: 交易类型为存证
//2:交易类型为现金
// transferType: 交易类型
//1: 银行转账给公司
//2: 公司与公司间转账
//3: 公司转账给银行
// 银行向公司交易(公司颁布凭证):
function bankToCompanyReceipt(
address senderAddress, // 凭证发送方
address accepterAddress, // 凭证接受方
uint amount, // 交易额
uint8 receiptType // 凭证类型
) public returns(uint){
// 银行转账给公司,银行是发票接受者,只有银行同意要发票,这笔交易才能执行
require(msg.sender == accepterAddress,"The function caller must be accper");
// 拿出银行、公司结构体
Company memory company = companyMap[senderAddress];
Bank memory bank = bankMap[accepterAddress];
// 判断公司银行是否存在
if(keccak256(bytes(bank.bankName)) == keccak256(bytes(""))){
return 404001;
}
if(keccak256(bytes(company.companyName)) == keccak256(bytes(""))){
return 404002;
}
// 判断银行资产是否小于转账额
if(bank.creditAsset < amount){
return 500001;
}
// 初始化凭证
Receipt memory newReceipt = Receipt(
senderAddress,
accepterAddress,
receiptType,
1,
amount
);
// 发票索引 + 1
receiptIndex += 1;
// 根据转账额,相互的 +-
companyMap[accepterAddress].creditAsset += amount;
bankMap[senderAddress].creditAsset -= amount;
// 存凭证索引,这样我们拿到公司或银行信息,拿到发票索引,在拿到发票结构体
receiptMap[receiptIndex] = newReceipt;
companyMap[accepterAddress].sendReceiptIndex.push(receiptIndex);
bankMap[senderAddress].acceptReceiptIndex.push(receiptIndex);
return 200;
}
//公司向公司交易(接受钱的公司需要颁布凭证)
function companyToCompanyReceipt(
address senderAddress,
address accepterAddress,
uint amount,
uint8 receiptType
) public returns(uint){
require(msg.sender == accepterAddress);
Company memory senderCompany = companyMap[senderAddress];
Company memory accepterCompany = companyMap[accepterAddress];
if (keccak256(bytes(senderCompany.companyName)) == keccak256(bytes(""))) {
return 404001;
}
//确认接收公司存在
if (keccak256(bytes(accepterCompany.companyName)) == keccak256(bytes(""))) {
return 404002;
}
//如果存证接收的公司资产小于存证数额,那么就不能交易发送存证
if (accepterCompany.creditAsset < amount) {
return 500001;
}
//创建存证
Receipt memory newReceipt = Receipt(
senderAddress,
accepterAddress,
receiptType,
2,
amount
);
receiptIndex += 1;
//记录存证(存证Map,公司Map对应地址的发送和接收存证列表)
receiptMap[receiptIndex] = newReceipt;
companyMap[senderAddress].sendReceiptIndex.push(receiptIndex);
companyMap[accepterAddress].acceptReceiptIndex.push(receiptIndex);
companyMap[senderAddress].creditAsset += amount;
companyMap[accepterAddress].creditAsset -= amount;
return 200;
}
//公司与银行交易(银行颁布凭证)
function companyToBankReceipt(
address senderAddress,
address accepterAddress,
uint amount,
uint8 receiptType
) public returns (uint) {
require(msg.sender == accepterAddress);
Bank memory bank = bankMap[senderAddress];
Company memory accepterCompany = companyMap[accepterAddress];
//确认发送公司存在
if (keccak256(bytes(bank.bankName)) == keccak256(bytes(""))) {
return 404001;
}
//确认接收公司存在
if (keccak256(bytes(accepterCompany.companyName)) == keccak256(bytes(""))) {
return 404002;
}
//如果存证接收的公司资产小于存证数额,那么就不能交易发送存证
if (accepterCompany.creditAsset < amount) {
return 500001;
}
//创建存证
Receipt memory newReceipt = Receipt(
senderAddress,
accepterAddress,
receiptType,
3,
amount
);
receiptIndex += 1;
//记录存证(存证Map,公司Map对应地址的发送和接收存证列表)
receiptMap[receiptIndex] = newReceipt;
bankMap[senderAddress].sendReceiptIndex.push(receiptIndex);
companyMap[accepterAddress].acceptReceiptIndex.push(receiptIndex);
bankMap[senderAddress].creditAsset += amount;
companyMap[accepterAddress].creditAsset -= amount;
return 200;
}
}