<1>  The first two sentences are correct.  dynamic_cast needs a class to be polymorphic.  It also is generally more expensive.  The rest, though....
sizeof() has absolutely nothing to do with how the cast behaves or whether or not it's safe/successful.
Also, static_cast will fail unless the types are related.  Example:
| 12
 3
 4
 5
 
 | class A {};
class B {};
A* a = new A;
B* b = static_cast<B*>(a);  // compiler error, A and B are not related 
 | 
<2>  This is false.  The only time you should "always" use static_cast is if you know for a fact the cast will be safe.  Again whether or not it's "safe" has nothing to do with the sizeof() the class.  See notes at the bottom.
<3>  This is false.  static_cast will correctly adjust the vtable as needed.
<4>  N/A, there is no issue in <3>.
Really, you are way overcomplicating things here.  static_cast and dynamic_cast are quite simple.  They are actually 
identical except for the below key points:
1)  dynamic_cast does a runtime check to make sure the cast is good.  This means it's generally slower.
2)  Also, because dynamic_cast does the runtime check, it's much safer.  There is zero risk of a bad cast going unnoticed.
3)  dynamic_cast requires the class to be polymorphic.  static_cast does not.
The only difference is the runtime check. But both casts cast the pointer the same way.
As for what a bad cast is...
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 
 | class Parent
{
public:
virtual ~Parent() {}  // make it polymorphic
};
class A : public Parent { };
class B : public Parent { };
int main()
{
  A a;
  B b;
  Parent* p = &a;  // p points to an 'A' object
  // how dynamic cast works:
  A* dyn_a = dynamic_cast<A*>(p);  // dynamic_cast checks 'p' to make sure it points to an 'A'
     // it does, so this cast is safe.  dynamic_cast succeeds.
  B* dyn_b = dynamic_cast<B*>(p);  // dynamic_cast checks 'p'.  It will see that 'p' does not
    // point to a 'B', so this is a bad cast.  dynamic_cast will fail and dyn_b will be == nullptr
  // how static_cast works
  A* sta_a = static_cast<A*>(p);  // static_cast assumes the cast is good.  No runtime check
    // sta_a will be identical to dyn_a above
  B* sta_b = static_cast<B*>(p);  // static_cast assumes the cast is good... BUT IT ISN'T
    //  'p' does not point to a 'B', so this is a bad cast!  static_cast succeeds, resulting in
    //  'sta_b' being a BAD POINTER.  Dereferencing sta_b has undefined behavior.
}
 | 
That's the difference.
Really... this means that when you have to downcast:
- use static_cast only if you are 100% sure the cast is good.
- use dynamic_cast if you are not sure.