Modify the following personal bank contract and signing program to make them secure against replay and cross-contract spend attacks. Your submission should be the solidity program AND the signing program.
PersonalBank.sol
pragma solidity ^0.5.0;
contract PersonalBank {
address owner;
constructor() public payable {
owner = msg.sender;
}
function() external payable {
}
function cashCheque(address payable to, uint256 amount,
bytes32 r, bytes32 s, uint8 v)
public {
bytes32 messageHash = keccak256(abi.encodePacked(to, amount));
bytes32 messageHash2 = keccak256(abi.encodePacked(
"\x19Ethereum Signed Message:\n32", messageHash
));
require(ecrecover(messageHash2, v, r, s) == owner, "bad signature");
to.transfer(amount);
}
}
sign-cheque.js
const ethers = require('ethers');
let privateKey = '0x4f3edf983ac636a65a842ce7c78d9aa706d3b113bce9c46f30d7d21715b23b1d';
// Cheque parameters
let to = '0xffcf8fdee72ac11b5c542428b35eef5769c409f0';
let amount = '1.0';
async function signPayment() {
let wallet = new ethers.Wallet(privateKey);
let amountWei = ethers.utils.parseEther(amount);
let message = ethers.utils.concat([
ethers.utils.hexZeroPad(to, 20),
ethers.utils.hexZeroPad(ethers.utils.hexlify(amountWei), 32),
]);
let messageHash = ethers.utils.keccak256(message);
let sig = await wallet.signMessage(ethers.utils.arrayify(messageHash));
let splitSig = ethers.utils.splitSignature(sig);
console.log(`to: ${to}`);
console.log(`amount: ${amountWei}`);
console.log();
console.log(`r: ${splitSig.r}`);
console.log(`s: ${splitSig.s}`);
console.log(`v: ${splitSig.v}`);
}
signPayment();