Skip to content

Commit 03f9df9

Browse files
committed
clean up, add `auth_as'
1 parent 64d8e9e commit 03f9df9

File tree

4 files changed

+59
-95
lines changed

4 files changed

+59
-95
lines changed

Dappfile

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name ds-auth
2-
description Basic authorization framework
3-
version K99
2+
description Simple access control pattern
3+
version K75
44

55
author Nikolai Mushegian <[email protected]>
66
author Daniel Brockman <[email protected]>

README.md

+4-7
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,18 @@ The `DSAuth` mixin is a widely-used Ethereum access control pattern.
66
The critical functionality is summarized by this part of the code:
77

88
modifier auth {
9-
if (!isAuthorized()) throw;
9+
assert(isAuthorized(msg.sender, msg.sig));
1010
_;
1111
}
1212

13-
function isAuthorized() internal returns (bool) {
14-
if (address(authority) == msg.sender) {
13+
function isAuthorized(address src, bytes4 sig) internal returns (bool) {
14+
if (src == address(authority)) {
1515
return true;
16-
} else if (address(authority) == 0) {
17-
return false;
1816
} else {
19-
return authority.canCall(msg.sender, this, msg.sig);
17+
return authority.canCall(src, this, sig);
2018
}
2119
}
2220

23-
2421
The `canCall` interface is defined on `DSIAuthority`:
2522

2623
contract DSAuthority {

src/auth.sol

+36-67
Original file line numberDiff line numberDiff line change
@@ -1,100 +1,69 @@
1-
/*
2-
Copyright 2016-2017 Nexus Development, LLC
1+
/// auth.sol -- widely-used access control pattern for Ethereum
32

4-
Licensed under the Apache License, Version 2.0 (the "License");
5-
you may not use this file except in compliance with the License.
6-
You may obtain a copy of the License at
3+
// Copyright (C) 2015, 2016, 2017 Nexus Development, LLC
74

8-
http://www.apache.org/licenses/LICENSE-2.0
5+
// Licensed under the Apache License, Version 2.0 (the "License").
6+
// You may not use this file except in compliance with the License.
97

10-
Unless required by applicable law or agreed to in writing, software
11-
distributed under the License is distributed on an "AS IS" BASIS,
12-
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
See the License for the specific language governing permissions and
14-
limitations under the License.
15-
*/
8+
// Unless required by applicable law or agreed to in writing, software
9+
// distributed under the License is distributed on an "AS IS" BASIS,
10+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND (express or implied).
1611

1712
pragma solidity ^0.4.8;
1813

19-
contract DSAuthEvents {
20-
event LogSetAuthority (address indexed authority);
21-
}
22-
23-
contract DSIAuth {
24-
function setAuthority(DSIAuthority newAuthority);
25-
}
26-
27-
// `DSAuthority` is the interface which `DSAuth`-derived objects expect
28-
// their authority to be when it is defined.
2914
contract DSIAuthority {
30-
// `canCall` will be called with these arguments in the caller's
31-
// scope if it is coming from an `auth` check (`isAuthorized` internal function):
32-
// `DSAuthority(_ds_authority).canCall(msg.sender, address(this), msg.sig);`
33-
function canCall( address caller
34-
, address code
35-
, bytes4 sig )
36-
constant
37-
returns (bool);
15+
function canCall(
16+
address src, address dst, bytes4 sig
17+
) constant returns (bool);
18+
}
3819

39-
function release(DSIAuth what);
20+
contract DSAuthEvents {
21+
event LogSetAuthority(address indexed authority);
4022
}
4123

42-
contract DSAuth is DSIAuth, DSAuthEvents {
24+
contract DSAuth is DSAuthEvents {
4325
DSIAuthority public authority;
4426

4527
function DSAuth() {
4628
authority = DSIAuthority(msg.sender);
4729
LogSetAuthority(authority);
4830
}
4931

50-
function setAuthority(DSIAuthority newAuthority)
32+
function setAuthority(address authority_)
5133
auth
5234
{
53-
authority = newAuthority;
35+
authority = DSIAuthority(authority_);
5436
LogSetAuthority(authority);
5537
}
5638

5739
modifier auth {
58-
if (!isAuthorized()) throw;
40+
assert(isAuthorized(msg.sender, msg.sig));
5941
_;
6042
}
6143

62-
function isAuthorized() internal returns (bool)
63-
{
64-
if ( address(authority) == msg.sender ) {
44+
modifier auth_as(string sig) {
45+
assert(isAuthorized(msg.sender, bytes4(sha3(sig))));
46+
_;
47+
}
48+
49+
function isAuthorized(address src, bytes4 sig) internal returns (bool) {
50+
if (src == address(authority)) {
6551
return true;
66-
} else if ( address(authority) == 0 ) {
67-
return false;
6852
} else {
69-
// WARNING, this must throw if calling empty code. This is only works
70-
// as of a recent compiler version. This is not clearly defined in
71-
// Solidity semantics so this behavior must have a dedicated test.
72-
return authority.canCall(msg.sender, this, msg.sig);
53+
// WARNING:
54+
//
55+
// This must throw if `authority' points to either (1) zero,
56+
// or (2) an address which has no code attached to it.
57+
//
58+
// This is not clearly defined in the semantics of Solidity
59+
// and only works as of a recent compiler version, so this
60+
// behavior must be tested explicitly.
61+
//
62+
return authority.canCall(src, this, sig);
7363
}
7464
}
75-
}
7665

77-
// An DSIAuthority implementation with standard `release`.
78-
// TODO possible leave canCall undefined?
79-
contract DSAuthority is DSIAuthority
80-
, DSAuth
81-
{
82-
// `canCall` will be called with these arguments in the caller's
83-
// scope if it is coming from an `auth` check (`isAuthorized` internal function):
84-
// `DSAuthority(_ds_authority).canCall(msg.sender, address(this), msg.sig);`
85-
function canCall( address caller
86-
, address code
87-
, bytes4 sig )
88-
constant
89-
returns (bool)
90-
{
91-
return false;
92-
}
93-
94-
function release(DSIAuth what)
95-
auth
96-
{
97-
what.setAuthority(DSIAuthority(msg.sender));
66+
function assert(bool x) {
67+
if (!x) throw;
9868
}
9969
}
100-

src/auth.t.sol

+17-19
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,17 @@ contract FakeVault is DSAuth {
1919
function access() auth {}
2020
}
2121

22-
contract BooleanAuthority is DSAuthority {
23-
bool value;
24-
function BooleanAuthority(bool _value) { value = _value; }
22+
contract BooleanAuthority is DSIAuthority {
23+
bool yes;
24+
25+
function BooleanAuthority(bool _yes) {
26+
yes = _yes;
27+
}
28+
2529
function canCall(
26-
address caller, address code, bytes4 sig
30+
address src, address dst, bytes4 sig
2731
) constant returns (bool) {
28-
return value;
32+
return yes;
2933
}
3034
}
3135

@@ -36,18 +40,18 @@ contract DSAuthTest is DSTest, DSAuthEvents {
3640
function test_owner() {
3741
expectEventsExact(vault);
3842
vault.access();
39-
vault.setAuthority(DSAuthority(0));
40-
LogSetAuthority(DSAuthority(0));
43+
vault.setAuthority(0);
44+
LogSetAuthority(0);
4145
}
4246

4347
function testFail_non_owner_1() {
44-
vault.setAuthority(DSAuthority(0));
48+
vault.setAuthority(0);
4549
vault.access();
4650
}
4751

4852
function testFail_non_owner_2() {
49-
vault.setAuthority(DSAuthority(0));
50-
vault.setAuthority(DSAuthority(0));
53+
vault.setAuthority(0);
54+
vault.setAuthority(0);
5155
}
5256

5357
function test_accepting_authority() {
@@ -57,20 +61,14 @@ contract DSAuthTest is DSTest, DSAuthEvents {
5761

5862
function testFail_rejecting_authority_1() {
5963
vault.setAuthority(new BooleanAuthority(false));
60-
vault.setAuthority(DSAuthority(0));
64+
vault.setAuthority(0);
6165
vault.access();
6266
}
6367

6468
function testFail_rejecting_authority_2() {
6569
vault.setAuthority(new BooleanAuthority(false));
66-
vault.setAuthority(DSAuthority(0));
67-
vault.setAuthority(DSAuthority(0));
68-
}
69-
70-
function testFail_rejecting_authority_3() {
71-
vault.setAuthority(new BooleanAuthority(false));
72-
vault.setAuthority(DSAuthority(0));
73-
vault.setAuthority(DSAuthority(0));
70+
vault.setAuthority(0);
71+
vault.setAuthority(0);
7472
}
7573
}
7674

0 commit comments

Comments
 (0)