我是新手,我为 POC 创建了我的第一个智能合约。这个想法是模拟一个预订过程,客人支付初始押金(unlockDoor 方法),当他离开房间时,他将根据使用时间获得退款。
我将事件连接到我的树莓派,以便打开相关房间的灯。
它适用于 javascript 虚拟机,但使用本地 RPC 我有一些问题,我不明白为什么。
- 使用 html 页面中的简单按钮,unlockDoor 和 lockDoor 方法不会打开元掩码弹出窗口以接受交易。控制台内没有错误。
- 将 remix 与本地 RPC 一起使用:解锁门有效,锁门生成错误错误:执行事务时 VM 异常:气体不足。很多文章说要增加gas值,但它不起作用。可能我错过了什么。我不明白什么。使用 javascript 虚拟机所有方法都可以正常工作。
- 使用 RPC(和测试网),lock 方法中的双重传输可能会产生一些奇怪的东西。这些双重操作正确吗?我必须以其他方式管理它们吗?
- 基于第 2 点和第 3 点:对如何使用“应付”指令产生了混淆。
Index.html 的 javascript
var web3 = new Web3(new
Web3.providers.HttpProvider("http://localhost:8545"));
web3.eth.defaultAccount = web3.eth.accounts[0];
var hotelReservation = web3.eth.contract(ABI);
var contract = hotelReservation.at(ADDRESS);
var room1_unlock = document.getElementById("room1");
room1_unlock.addEventListener("click", function(){
console.log("here");
contract.unlockDoor(1);
});
var room1_lock = document.getElementById("room1_lock");
room1_lock.addEventListener("click", function(){
console.log("here");
contract.lockDoor(1);
});
合同。注意:成本是每秒仅用于测试pourpose
contract HotelReservation{
//the owner of the contract
address owner;
//used for forcing the door lock
address raspberryAccount = XXXXXXXXX;
uint constant roomsNumber = 5;
//roomsNumber - sender
mapping (uint => address) reservations;
//address - deposit
mapping (address => uint) deposits;
//address - checkin timestamp
mapping (address => uint) checkins;
uint depositFee = 1 ether;
uint costPerSeconds = 0.0000115 ether;
event doorStatus (bool status, uint roomNr);
function HotelReservation (){
owner = msg.sender;
//init reservations
for (uint i=1; i <= roomsNumber; i++)
{
reservations[i] == 0;
}
}
modifier canReserveRoom(uint roomNr) {
bool canReserve = true;
if(roomNr <= 0 || roomNr > 5)
canReserve = false;
//check if sender has another camera reserved
for (uint i=1; i<= roomsNumber ; i++)
{
if (reservations[i] == msg.sender){
canReserve = false;
}
}
//camera is available
if(reservations[roomNr] != 0)
{
canReserve = false;
}
//money for deposit are enought
if(msg.value < depositFee)
{
canReserve = false;
}
require(canReserve);
_;
}
function unlockDoor(uint roomNr) canReserveRoom(roomNr) public payable returns (bool){
deposits[msg.sender] = depositFee;
reservations[roomNr] = msg.sender;
checkins[msg.sender] = block.timestamp;
doorStatus(true, roomNr);
return true;
}
modifier canLeaveRoom(uint roomNr) {
bool canLeave = true;
//no pending reservation
if (reservations[roomNr] != msg.sender){
canLeave = false;
}
require(canLeave);
_;
}
modifier isTheOwner(){
bool forceRoomLock = true;
if(msg.sender != raspberryAccount)
forceRoomLock = false;
require(forceRoomLock);
_;
}
function forceLockDoor(uint roomNr) isTheOwner public returns (bool){
address tenantAddress = reservations[roomNr];
//retrieve all deposit
owner.transfer(deposits[tenantAddress]);
reservations[roomNr] = 0;
deposits[tenantAddress] = 0;
checkins[tenantAddress] = 0;
doorStatus(false, roomNr);
return true;
}
function lockDoor(uint roomNr) canLeaveRoom(roomNr) public payable returns (bool){
//calculate the cost for the usage of the room
uint checkinTimestamp = checkins[msg.sender];
uint datetimeNow = block.timestamp;
uint usage = datetimeNow - checkinTimestamp;
uint usageInSeconds = uint8(usage % 60);
uint totalCost = usageInSeconds * costPerSeconds;
uint refound = deposits[msg.sender] - totalCost;
//send money back (deposit - usage)
msg.sender.transfer(refound);
//send money back to the hotel owner
owner.transfer(totalCost);
//clean information
reservations[roomNr] = 0;
deposits[msg.sender] = 0;
checkins[msg.sender] = 0;
doorStatus(false, roomNr);
return true;
}
}