Improve Smart Contract Structure¶
Now we know our basic functionality, we can structure the smart contract differently. To make it easier to read, we can break the functionality down into two distinct smart contracts.
Note
Note that since Allowance is Ownable, and the SharedWallet is Allowance, therefore by commutative property, SharedWallet is also Ownable.
//SPDX-License-Identifier: MIT
pragma solidity 0.8.1;
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/Ownable.sol";
contract Allowance is Ownable {
function isOwner() internal view returns(bool) {
return owner() == msg.sender;
}
mapping(address => uint) public allowance;
function setAllowance(address _who, uint _amount) public onlyOwner {
allowance[_who] = _amount;
}
modifier ownerOrAllowed(uint _amount) {
require(isOwner() || allowance[msg.sender] >= _amount, "You are not allowed!");
_;
}
function reduceAllowance(address _who, uint _amount) internal ownerOrAllowed(_amount) {
allowance[_who] -= _amount;
}
}
contract SharedWallet is Allowance {
function withdrawMoney(address payable _to, uint _amount) public ownerOrAllowed(_amount) {
require(_amount <= address(this).balance, "Contract doesn't own enough money");
if(!isOwner()) {
reduceAllowance(msg.sender, _amount);
}
_to.transfer(_amount);
}
receive() external payable {
}
}
Both contracts are still in the same file, so we don't have any imports (yet). That's something for another lecture later on. Right now, the important part to understand is inheritance.