Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: set and allow LAND as part of an Estate data by LAND updateOperator #131

Merged
merged 3 commits into from Apr 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 28 additions & 1 deletion contracts/estate/EstateRegistry.sol
Expand Up @@ -34,6 +34,11 @@ contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Recei
_;
}

modifier onlyLandUpdateAuthorized(uint256 estateId, uint256 landId) {
require(_isLandUpdateAuthorized(msg.sender, estateId, landId), "unauthorized user");
_;
}

/**
* @dev Mint a new Estate with some metadata
* @param to The address that will own the minted token
Expand Down Expand Up @@ -148,6 +153,18 @@ contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Recei
emit UpdateOperator(estateId, operator);
}

function setLandUpdateOperator(
uint256 estateId,
uint256 landId,
address operator
)
public
canTransfer(estateId)
{
require(landIdEstate[landId] == estateId, "The LAND is not part of the Estate");
registry.setUpdateOperator(landId, operator);
}

function initialize(
string _name,
string _symbol,
Expand Down Expand Up @@ -419,6 +436,16 @@ contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Recei
return isApprovedOrOwner(operator, estateId) || updateOperator[estateId] == operator;
}

function _isLandUpdateAuthorized(
address operator,
uint256 estateId,
uint256 landId
)
internal returns (bool)
{
return _isUpdateAuthorized(operator, estateId) || registry.updateOperator(landId) == operator;
}

function _bytesToUint(bytes b) internal pure returns (uint256) {
return uint256(_bytesToBytes32(b));
}
Expand All @@ -439,7 +466,7 @@ contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Recei
string data
)
internal
onlyUpdateAuthorized(estateId)
onlyLandUpdateAuthorized(estateId, landId)
{
require(landIdEstate[landId] == estateId, "The LAND is not part of the Estate");
int x;
Expand Down
2 changes: 2 additions & 0 deletions contracts/estate/EstateStorage.sol
Expand Up @@ -4,9 +4,11 @@ pragma solidity ^0.4.23;
contract LANDRegistry {
function decodeTokenId(uint value) external pure returns (int, int);
function updateLandData(int x, int y, string data) external;
function setUpdateOperator(uint256 assetId, address operator) external;
function ping() public;
function ownerOf(uint256 tokenId) public returns (address);
function safeTransferFrom(address, address, uint256) public;
function updateOperator(uint256 landId) public returns (address);
}


Expand Down
31 changes: 30 additions & 1 deletion full/EstateRegistry.sol
Expand Up @@ -994,9 +994,11 @@ contract IEstateRegistry {
contract LANDRegistry {
function decodeTokenId(uint value) external pure returns (int, int);
function updateLandData(int x, int y, string data) external;
function setUpdateOperator(uint256 assetId, address operator) external;
function ping() public;
function ownerOf(uint256 tokenId) public returns (address);
function safeTransferFrom(address, address, uint256) public;
function updateOperator(uint256 landId) public returns (address);
}


Expand Down Expand Up @@ -1050,6 +1052,11 @@ contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Recei
_;
}

modifier onlyLandUpdateAuthorized(uint256 estateId, uint256 landId) {
require(_isLandUpdateAuthorized(msg.sender, estateId, landId), "unauthorized user");
_;
}

/**
* @dev Mint a new Estate with some metadata
* @param to The address that will own the minted token
Expand Down Expand Up @@ -1164,6 +1171,18 @@ contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Recei
emit UpdateOperator(estateId, operator);
}

function setLandUpdateOperator(
uint256 estateId,
uint256 landId,
address operator
)
public
canTransfer(estateId)
{
require(landIdEstate[landId] == estateId, "The LAND is not part of the Estate");
registry.setUpdateOperator(landId, operator);
}

function initialize(
string _name,
string _symbol,
Expand Down Expand Up @@ -1435,6 +1454,16 @@ contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Recei
return isApprovedOrOwner(operator, estateId) || updateOperator[estateId] == operator;
}

function _isLandUpdateAuthorized(
address operator,
uint256 estateId,
uint256 landId
)
internal returns (bool)
{
return _isUpdateAuthorized(operator, estateId) || registry.updateOperator(landId) == operator;
}

function _bytesToUint(bytes b) internal pure returns (uint256) {
return uint256(_bytesToBytes32(b));
}
Expand All @@ -1455,7 +1484,7 @@ contract EstateRegistry is Migratable, IEstateRegistry, ERC721Token, ERC721Recei
string data
)
internal
onlyUpdateAuthorized(estateId)
onlyLandUpdateAuthorized(estateId, landId)
{
require(landIdEstate[landId] == estateId, "The LAND is not part of the Estate");
int x;
Expand Down
107 changes: 106 additions & 1 deletion test/EstateRegistry.js
Expand Up @@ -680,6 +680,14 @@ contract('EstateRegistry', accounts => {
data.should.be.equal('newValue')
})

it('should allow a LAND updateOperator to update LAND data', async function() {
const estateId = await createUserEstateWithToken1()
await estate.setLandUpdateOperator(estateId, 1, anotherUser, sentByUser)
await estate.updateLandData(estateId, 1, 'newValue', sentByAnotherUser)
const data = await land.landData(0, 1, sentByUser)
data.should.be.equal('newValue')
})

it('should not allow owner an Estate to update LAND data of an Estate which is not the owner', async function() {
await land.assignMultipleParcels([0], [1], user, sentByCreator)
const estateIdByUser = await createEstate([0], [1], user, sentByUser)
Expand All @@ -690,7 +698,7 @@ contract('EstateRegistry', accounts => {
)
})

it('should not allow neither operator, nor owner nor updateOperator of an Estate to update LAND data', async function() {
it('should not allow neither operator, nor owner nor updateOperator nor LAND updateOperator of an Estate to update LAND data', async function() {
await land.assignMultipleParcels([0], [1], user, sentByCreator)
const estateId = await createEstate([0], [1], user, sentByUser)
await assertRevert(
Expand Down Expand Up @@ -959,4 +967,101 @@ contract('EstateRegistry', accounts => {
owner.should.be.equal(anotherUser)
})
})

describe('Update LAND Update Operator', function() {
it('should update LAND updateOperator by estate owner', async function() {
const estateId = await createUserEstateWithToken1()
await estate.setLandUpdateOperator(estateId, 1, anotherUser, sentByUser)
const updateOperator = await land.updateOperator(1)
updateOperator.should.be.equal(anotherUser)
})

it('should update LAND updateOperator by estate operator', async function() {
const estateId = await createUserEstateWithToken1()
await estate.approve(anotherUser, estateId, sentByUser)
await estate.setLandUpdateOperator(
estateId,
1,
yetAnotherUser,
sentByAnotherUser
)
const updateOperator = await land.updateOperator(1)
updateOperator.should.be.equal(yetAnotherUser)
})

it('should clean LAND updateOperator', async function() {
const estateId = await createUserEstateWithToken1()
await estate.setLandUpdateOperator(
estateId,
1,
yetAnotherUser,
sentByUser
)
let updateOperator = await land.updateOperator(1)
updateOperator.should.be.equal(yetAnotherUser)

await estate.setLandUpdateOperator(estateId, 1, EMPTY_ADDRESS, sentByUser)
updateOperator = await land.updateOperator(1)
updateOperator.should.be.equal(EMPTY_ADDRESS)

await estate.approve(anotherUser, estateId, sentByUser)
await estate.setLandUpdateOperator(
estateId,
1,
yetAnotherUser,
sentByAnotherUser
)
updateOperator = await land.updateOperator(1)
updateOperator.should.be.equal(yetAnotherUser)

await estate.setLandUpdateOperator(
estateId,
1,
EMPTY_ADDRESS,
sentByAnotherUser
)
updateOperator = await land.updateOperator(1)
updateOperator.should.be.equal(EMPTY_ADDRESS)
})

it('reverts when updating LAND updateOperator by estate updateOperator', async function() {
const estateId = await createUserEstateWithToken1()
await estate.setUpdateOperator(estateId, anotherUser, sentByUser)
await assertRevert(
estate.setLandUpdateOperator(
estateId,
2,
yetAnotherUser,
sentByAnotherUser
)
)
})

it('reverts when updating LAND updateOperator for a LAND outside the estate', async function() {
const estateId = await createUserEstateWithToken1()
await assertRevert(
estate.setLandUpdateOperator(estateId, 2, anotherUser, sentByUser)
)
})

it('reverts when updating LAND updateOperator for a LAND from another estate', async function() {
const estateId = await createUserEstateWithToken1()
await createUserEstateWithToken2()
await assertRevert(
estate.setLandUpdateOperator(estateId, 2, anotherUser, sentByUser)
)
})

it('reverts when updating LAND updateOperator by hacker', async function() {
const estateId = await createUserEstateWithToken1()
await assertRevert(
estate.setLandUpdateOperator(
estateId,
1,
anotherUser,
sentByAnotherUser
)
)
})
})
})